solocraft + dynamicxp
This commit is contained in:
71
dep/g3dlite/CMakeLists.txt
Normal file
71
dep/g3dlite/CMakeLists.txt
Normal file
@@ -0,0 +1,71 @@
|
||||
# Copyright (C) 2008-2014 TrinityCore <http://www.trinitycore.org/>
|
||||
#
|
||||
# This file is free software; as a special exception the author gives
|
||||
# unlimited permission to copy and/or distribute it, with or without
|
||||
# modifications, as long as this notice is preserved.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful, but
|
||||
# WITHOUT ANY WARRANTY, to the extent permitted by law; without even the
|
||||
# implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
set(g3dlib_STAT_SRCS
|
||||
source/AABox.cpp
|
||||
source/Any.cpp
|
||||
source/AnyTableReader.cpp
|
||||
source/BinaryFormat.cpp
|
||||
source/BinaryInput.cpp
|
||||
source/BinaryOutput.cpp
|
||||
source/Box.cpp
|
||||
source/Capsule.cpp
|
||||
source/CollisionDetection.cpp
|
||||
source/CoordinateFrame.cpp
|
||||
source/Crypto.cpp
|
||||
source/Cylinder.cpp
|
||||
source/debugAssert.cpp
|
||||
source/FileSystem.cpp
|
||||
source/fileutils.cpp
|
||||
source/format.cpp
|
||||
source/g3dfnmatch.cpp
|
||||
source/g3dmath.cpp
|
||||
source/GThread.cpp
|
||||
source/Line.cpp
|
||||
source/LineSegment.cpp
|
||||
source/Log.cpp
|
||||
source/Matrix3.cpp
|
||||
source/Matrix4.cpp
|
||||
source/MemoryManager.cpp
|
||||
source/PhysicsFrame.cpp
|
||||
source/Plane.cpp
|
||||
source/prompt.cpp
|
||||
source/Quat.cpp
|
||||
source/Random.cpp
|
||||
source/Ray.cpp
|
||||
source/RegistryUtil.cpp
|
||||
source/Sphere.cpp
|
||||
source/stringutils.cpp
|
||||
source/System.cpp
|
||||
source/TextInput.cpp
|
||||
source/TextOutput.cpp
|
||||
source/Triangle.cpp
|
||||
source/uint128.cpp
|
||||
source/UprightFrame.cpp
|
||||
source/Vector2.cpp
|
||||
source/Vector3.cpp
|
||||
source/Vector4.cpp
|
||||
)
|
||||
|
||||
add_library(g3dlib STATIC ${g3dlib_STAT_SRCS})
|
||||
|
||||
target_include_directories(g3dlib
|
||||
PUBLIC
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include)
|
||||
|
||||
target_link_libraries(g3dlib
|
||||
PUBLIC
|
||||
zlib
|
||||
threads)
|
||||
|
||||
set_target_properties(g3dlib
|
||||
PROPERTIES
|
||||
FOLDER
|
||||
"dep")
|
||||
14
dep/g3dlite/Readme.txt
Normal file
14
dep/g3dlite/Readme.txt
Normal file
@@ -0,0 +1,14 @@
|
||||
Due to issues with G3D normally requiring X11 and the ZIP-library, the library version in this sourcetree contains a modified version.
|
||||
The applied patches are added as .diff-files to the repository for future reference (knowing what was changed is quite handy).
|
||||
|
||||
G3D-v8.0_hotfix1.diff - 2010-08-27 - remove dependency on zip/z11 libraries, add support for 64-bit arch
|
||||
G3D-v8.0_hotfix2.diff - 2012-01-14 - fix typo in isNaN(float x)
|
||||
G3D-v8.0_hotfix3.diff - 2012-08-26 - fix compilation on Fedora Linux
|
||||
G3D-v8.0_hotfix4.diff - 2012-11-09 - fix compilation on OSX
|
||||
G3D-v8.0_hotfix5.diff - 2013-02-27 - fix compilation in cygwin environments
|
||||
G3D-v8.0_hotfix6.diff - 2013-03-08 - fix compilation in mingw
|
||||
G3D-v8.0_hotfix7.diff - 2013-08-31 - fix typo in Matrix4 == operator
|
||||
G3D-v8.0_hotfix8.diff - 2013-09-01 - fix typo in Vector3int32 += operator
|
||||
G3D-v8.0_hotfix9.diff - 2014-06-01 - only VS < 10 don't ship inttypes.h
|
||||
G3D-v9.0 hotfix1.diff - 2014-08-22 - updated to G3D9, reapplied previous patches and removed unneeded changes
|
||||
G3D-v9.0 hotfix2.diff - 2014-08-23 - fix some -Wconversion warnings
|
||||
346
dep/g3dlite/include/G3D/AABox.h
Normal file
346
dep/g3dlite/include/G3D/AABox.h
Normal file
@@ -0,0 +1,346 @@
|
||||
/**
|
||||
\file G3D/AABox.h
|
||||
|
||||
Axis-aligned box class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2004-01-10
|
||||
\edited 2013-04-13
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_AABox_h
|
||||
#define G3D_AABox_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
An axis-aligned box.
|
||||
*/
|
||||
class AABox {
|
||||
private:
|
||||
friend class Intersect;
|
||||
|
||||
/** Optional argument placeholder */
|
||||
static int dummy;
|
||||
|
||||
/** NaN if empty */
|
||||
Point3 lo;
|
||||
|
||||
/** NaN if empty */
|
||||
Point3 hi;
|
||||
|
||||
public:
|
||||
|
||||
/** Creates the empty bounds, i.e., an empty set of points. */
|
||||
AABox() : lo(fnan(), fnan(), fnan()), hi(fnan(), fnan(), fnan()) {}
|
||||
|
||||
/**
|
||||
Constructs a zero-volume AABox at v.
|
||||
*/
|
||||
explicit AABox(const Point3& v) {
|
||||
lo = hi = v;
|
||||
}
|
||||
|
||||
/** Format is one of:
|
||||
- AABox(lowpoint, highpoint)
|
||||
- AABox(point)
|
||||
- AABox::empty()
|
||||
- AABox::inf()
|
||||
*/
|
||||
explicit AABox(const class Any& a);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
bool isEmpty() const {
|
||||
return lo.isNaN();
|
||||
}
|
||||
|
||||
/** 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>
|
||||
*/
|
||||
AABox(const Point3& low, const Point3& high) {
|
||||
set(low, high);
|
||||
}
|
||||
|
||||
AABox operator*(float f) const {
|
||||
if (f < 0) {
|
||||
return AABox(hi * f, lo * f);
|
||||
} else {
|
||||
return AABox(lo * f, hi * f);
|
||||
}
|
||||
}
|
||||
|
||||
AABox operator/(float f) const {
|
||||
return *this * (1.0f / f);
|
||||
}
|
||||
|
||||
/** Assumes that low is less than or equal to high along each dimension.
|
||||
*/
|
||||
inline void set(const Point3& low, const Point3& high) {
|
||||
debugAssert(
|
||||
(low.x <= high.x) &&
|
||||
(low.y <= high.y) &&
|
||||
(low.z <= high.z));
|
||||
debugAssert(! low.isNaN() && ! high.isNaN());
|
||||
lo = low;
|
||||
hi = high;
|
||||
}
|
||||
|
||||
/**
|
||||
Grows to include the bounds of \a a
|
||||
*/
|
||||
inline void merge(const AABox& a) {
|
||||
if (isEmpty()) {
|
||||
lo = a.lo;
|
||||
hi = a.hi;
|
||||
} else if (! a.isEmpty()) {
|
||||
lo = lo.min(a.lo);
|
||||
hi = hi.max(a.hi);
|
||||
}
|
||||
}
|
||||
|
||||
inline void merge(const Point3& a) {
|
||||
if (isEmpty()) {
|
||||
lo = hi = a;
|
||||
} else {
|
||||
lo = lo.min(a);
|
||||
hi = hi.max(a);
|
||||
}
|
||||
}
|
||||
|
||||
void merge(const class Box& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
inline bool isFinite() const {
|
||||
return isEmpty() || (lo.isFinite() && hi.isFinite());
|
||||
}
|
||||
|
||||
/** Returns not-a-number if empty */
|
||||
inline const Point3& low() const {
|
||||
return lo;
|
||||
}
|
||||
|
||||
/** Returns not-a-number if empty */
|
||||
inline const Point3& high() const {
|
||||
return hi;
|
||||
}
|
||||
|
||||
/**
|
||||
The largest possible finite box.
|
||||
*/
|
||||
static const AABox& maxFinite();
|
||||
|
||||
/** A large finite box. This is smaller than FLT_MAX
|
||||
because it leaves room to add boxes together. */
|
||||
static const AABox& large();
|
||||
|
||||
static const AABox& inf();
|
||||
|
||||
static const AABox& zero();
|
||||
|
||||
static const AABox& empty();
|
||||
|
||||
/**
|
||||
Returns the centroid of the box (NaN if empty)
|
||||
*/
|
||||
inline Point3 center() const {
|
||||
return (lo + hi) * 0.5;
|
||||
}
|
||||
|
||||
Point3 corner(int index) const;
|
||||
|
||||
/**
|
||||
Distance from corner(0) to the next corner along axis a.
|
||||
*/
|
||||
inline float extent(int a) const {
|
||||
if (isEmpty()) {
|
||||
return 0.0f;
|
||||
}
|
||||
debugAssert(a < 3);
|
||||
return hi[a] - lo[a];
|
||||
}
|
||||
|
||||
|
||||
inline Vector3 extent() const {
|
||||
if (isEmpty()) {
|
||||
return Vector3::zero();
|
||||
}
|
||||
return hi - lo;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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 = 0xFFFFFFFF) const;
|
||||
|
||||
/** less than or equal to containment */
|
||||
inline bool contains(const AABox& other) const {
|
||||
return
|
||||
(other.hi.x <= hi.x) &&
|
||||
(other.hi.y <= hi.y) &&
|
||||
(other.hi.z <= hi.z) &&
|
||||
(other.lo.x >= lo.x) &&
|
||||
(other.lo.y >= lo.y) &&
|
||||
(other.lo.z >= lo.z);
|
||||
}
|
||||
|
||||
inline bool contains(const Point3& 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);
|
||||
}
|
||||
|
||||
inline float area() const {
|
||||
if (isEmpty()) { return 0; }
|
||||
Vector3 diag = hi - lo;
|
||||
return 2.0f * (diag.x * diag.y + diag.y * diag.z + diag.x * diag.z);
|
||||
}
|
||||
|
||||
inline float volume() const {
|
||||
if (isEmpty()) { return 0; }
|
||||
Vector3 diag = hi - lo;
|
||||
return diag.x * diag.y * diag.z;
|
||||
}
|
||||
|
||||
Point3 randomInteriorPoint() const;
|
||||
|
||||
Point3 randomSurfacePoint() 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 Sphere& other) const;
|
||||
|
||||
/** Return the intersection of the two boxes */
|
||||
AABox intersect(const AABox& other) const {
|
||||
if (isEmpty() || other.isEmpty()) {
|
||||
return empty();
|
||||
}
|
||||
|
||||
const Point3& H = hi.min(other.hi);
|
||||
const Point3& L = lo.max(other.lo).min(H);
|
||||
|
||||
if (H.x < L.x && H.y < L.y && H.z < L.z) {
|
||||
return empty();
|
||||
} else {
|
||||
return AABox(L, H);
|
||||
}
|
||||
}
|
||||
|
||||
inline size_t hashCode() const {
|
||||
return lo.hashCode() + hi.hashCode();
|
||||
}
|
||||
|
||||
inline bool operator==(const AABox& b) const {
|
||||
if (isEmpty() && b.isEmpty()) {
|
||||
return true;
|
||||
} else {
|
||||
return (lo == b.lo) && (hi == b.hi);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool operator!=(const AABox& b) const {
|
||||
if (isEmpty()) {
|
||||
return b.isEmpty();
|
||||
} else {
|
||||
return !((lo == b.lo) && (hi == b.hi));
|
||||
}
|
||||
}
|
||||
|
||||
inline AABox operator+(const Vector3& v) const {
|
||||
AABox out;
|
||||
out.lo = lo + v;
|
||||
out.hi = hi + v;
|
||||
return out;
|
||||
}
|
||||
|
||||
inline AABox operator-(const Vector3& v) const {
|
||||
AABox out;
|
||||
out.lo = lo - v;
|
||||
out.hi = hi - v;
|
||||
return out;
|
||||
}
|
||||
|
||||
void getBounds(AABox& out) const {
|
||||
out = *this;
|
||||
}
|
||||
|
||||
void getBounds(Sphere& out) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <> struct HashTrait<G3D::AABox> {
|
||||
static size_t hashCode(const G3D::AABox& key) { return key.hashCode(); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
1024
dep/g3dlite/include/G3D/Any.h
Normal file
1024
dep/g3dlite/include/G3D/Any.h
Normal file
File diff suppressed because it is too large
Load Diff
512
dep/g3dlite/include/G3D/AnyVal.h
Normal file
512
dep/g3dlite/include/G3D/AnyVal.h
Normal file
@@ -0,0 +1,512 @@
|
||||
/**
|
||||
@file AnyVal.h
|
||||
@author Morgan McGuire
|
||||
@created 2006-06-11
|
||||
@edited 2008-07-14
|
||||
*/
|
||||
|
||||
#ifndef G3D_ANYVAL_H
|
||||
#define G3D_ANYVAL_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/TextInput.h"
|
||||
|
||||
namespace G3D {
|
||||
// Forward declarations for G3D types
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
class Color1;
|
||||
class Color3;
|
||||
class Color4;
|
||||
class Quat;
|
||||
class Matrix2;
|
||||
class Matrix3;
|
||||
class Matrix4;
|
||||
class CoordinateFrame;
|
||||
class TextInput;
|
||||
class TextOutput;
|
||||
class BinaryInput;
|
||||
class BinaryOutput;
|
||||
class Rect2D;
|
||||
class AABox;
|
||||
|
||||
/**
|
||||
\deprecated
|
||||
<b>Use the G3D::Any class instead. This is only provided for
|
||||
backwards compatibility to G3D 7.xx.</b>
|
||||
|
||||
A generic value, useful for defining property trees that can
|
||||
be loaded from and saved to disk. The values are intentionally
|
||||
restricted to a small set.
|
||||
|
||||
When written to files, the syntax is as follows. Note that you can
|
||||
nest arrays and tables in order to create full tree (i.e., XML-like)
|
||||
structures as configuration files:
|
||||
|
||||
<table>
|
||||
<tr><td>NULL</td><td><code>Nil</code></td></tr>
|
||||
<tr><td>double</td><td><i>The number in printf double format</i></td></tr>
|
||||
<tr><td>bool</td><td><code>true</code> <i>or</i> <code>false</code></td></tr>
|
||||
<tr><td>std::string</td><td><i>The string in double-quotes (</i><code>"</code><i>)</i></td></tr>
|
||||
<tr><td>Rect2D</td><td><code>R(</code><i>x<sub>0</sub></i><code>,</code><i>y<sub>0</sub></i><code>,</code><i>x<sub>1</sub></i><code>,</code><i>y<sub>1</sub></i><code>)</code></td></tr>
|
||||
<tr><td>Color1</td><td><code>C1(</code><i>value</i><code>)</code></td></tr>
|
||||
<tr><td>Color3</td><td><code>C3(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>)</code></td></tr>
|
||||
<tr><td>Color4</td><td><code>C4(</code><i>r</i><code>,</code><i>g</i><code>,</code><i>b</i><code>,</code><i>a</i><code>)</code></td></tr>
|
||||
<tr><td>Vector2</td><td><code>V2(</code><i>x</i><code>,</code><i>y</i><code>)</code></td></tr>
|
||||
<tr><td>Vector3</td><td><code>V3(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>)</code></td></tr>
|
||||
<tr><td>Vector4</td><td><code>V4(</code><i>x</i><code>,</code><i>y</i><code>,</code><i>z</i><code>,</code><i>w</i><code>)</code></td></tr>
|
||||
<tr><td>Quat</td><td><code>V(</code>x<code>,</code>y<code>,</code>z<code>,</code>w<code>)</code></td></tr>
|
||||
<tr><td>AABox</td><td><code>AAB(</code>low Vector3<code>, </code>high Vector3<code>)</code></td></tr>
|
||||
<tr><td>Matrix2</td><td><code>M2(</code>r0c0<code>, </code>r0c1<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>)</code></td></tr>
|
||||
<tr><td>Matrix3</td><td><code>M3(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>)</code></td></tr>
|
||||
<tr><td>Matrix4</td><td><code>M4(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>,
|
||||
<br> </code>r3c0<code>, </code>r3c1<code>, </code>r3c2<code>, </code>r3c3<code>)</code></td></tr>
|
||||
<tr><td>CoordinateFrame</td><td><code>CF(</code>r0c0<code>, </code>r0c1<code>, </code>r0c2<code>, </code>r0c3<code>,
|
||||
<br> </code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
|
||||
<br> </code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>)</code></td></tr>
|
||||
<tr><td>CoordinateFrame</td><td><code>CF(V3(</code><i>x</i><code>, </code><i>y</i><code>, </code><i>z</i><code>), </code><i>yaw deg</i><code>, </code><i>pitch deg</i><code>, </code><i>optional roll deg</i><code>)</code></td></tr>
|
||||
|
||||
<tr><td>Array</td><td><code>[</code><i>element<sub>0</sub></i><code>, </code><i>element<sub>1</sub></i><code>, </code> ... <code>, </code><i>element<sub>n-1</sub></i><code>]</code></td></tr>
|
||||
<tr><td>Table</td><td><code>{</code><i>symbol<sub>0</sub></i><code> = </code><i>value<sub>0</sub></i>
|
||||
<br><code> </code><i>symbol<sub>1</sub></i><code> = </code><i>value<sub>1</sub></i>
|
||||
<br><code> </code>...
|
||||
<br><code> </code><i>symbol<sub>n-1</sub></i><code> = </code><i>value<sub>n-1</sub></i><code>}</code></td></tr>
|
||||
</table>
|
||||
|
||||
See also boost::any for a more general purpose but slightly harder to use
|
||||
"any" for C++.
|
||||
|
||||
The semantics of operator[] and the get() methods are slightly different;
|
||||
operator[] acts more like a scripting language that automatically extends
|
||||
arrays and tables instead of generating errors. get() has more strict semantics,
|
||||
like a C++ class.
|
||||
|
||||
AnyVal uses copy-on-mutate, so that <code>AnyVal a = b</code> semantically copies <code>b</code> (like <code>int a = b</code> would), although in practice
|
||||
it delays the copy until one is mutated so that it is still fast to "copy" large arrays and tables.
|
||||
|
||||
Reading example:
|
||||
<pre>
|
||||
AnyVal property = AnyVal::fromFile("c:/tmp/test.txt"));
|
||||
|
||||
Vector3 vel = property["angular velocity"]
|
||||
|
||||
<i>Using defaults to handle errors:
|
||||
If there was no "enabled" value, this will return the default instead of failing</i>
|
||||
bool enabled = property["enabled"].boolean(true);
|
||||
|
||||
</pre>
|
||||
|
||||
Writing to a file:
|
||||
<pre>
|
||||
AnyVal dict(AnyVal::TABLE);
|
||||
|
||||
dict["enabled"] = AnyVal(true);
|
||||
dict["weight"] = 100;
|
||||
dict["angular velocity"] = Vector3(1, -3, 4.5);
|
||||
|
||||
TextOutput t("c:/tmp/test.txt");
|
||||
dict.serialize(t);
|
||||
t.commit();
|
||||
</pre>
|
||||
|
||||
Example of a data file:
|
||||
<pre>
|
||||
{
|
||||
heights = [1, 17, 32]
|
||||
model =
|
||||
{
|
||||
color = C3(1, 1, 1)
|
||||
filename = "foo.md2"
|
||||
}
|
||||
position = V3(23, 14, 0)
|
||||
name = "Elmer"
|
||||
}
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>What's the difference from boost::any?</b>
|
||||
<br>I think that AnyVal will be easier for novice C++ users. It addresses the problem that
|
||||
even though G3D::TextInput makes reading configuration files extremely simple, many people
|
||||
still don't use it. So AnyVal makes it ridiculously simple to read and write a tree of G3D
|
||||
types to a file.
|
||||
|
||||
<i>AnyVal:</i>
|
||||
<pre>
|
||||
{
|
||||
AnyVal tree(TextInput("config.txt"));
|
||||
|
||||
bool enabled = tree.get("enabled", false);
|
||||
Vector3 direction = tree.get("direction", Vector3::zero());
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
<i>boost:</i>
|
||||
<pre>
|
||||
{
|
||||
bool enabled = false;
|
||||
Vector3 direction;
|
||||
Table<boost::any> tree;
|
||||
|
||||
...write lots of file parsing code...
|
||||
|
||||
if (tree.containsKey("enabled")) {
|
||||
const boost::any& val = tree["enabled"];
|
||||
try {
|
||||
enabled = any_cast<bool>(val);
|
||||
} catch(const boost::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
|
||||
if (tree.containsKey("direction")) {
|
||||
const boost::any& val = tree["direction"];
|
||||
try {
|
||||
direction = any_cast<Vector3>(val);
|
||||
} catch(const boost::bad_any_cast &) {
|
||||
}
|
||||
}
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
|
||||
\deprecated
|
||||
*/
|
||||
class AnyVal {
|
||||
public:
|
||||
|
||||
/** Array and table values are all Any.*/
|
||||
enum Type {
|
||||
NIL,
|
||||
NUMBER,
|
||||
BOOLEAN,
|
||||
STRING,
|
||||
VECTOR2,
|
||||
VECTOR3,
|
||||
VECTOR4,
|
||||
MATRIX2,
|
||||
MATRIX3,
|
||||
MATRIX4,
|
||||
QUAT,
|
||||
COORDINATEFRAME,
|
||||
COORDINATEFRAME2D,
|
||||
CFRAME = COORDINATEFRAME,
|
||||
CFRAME2D = COORDINATEFRAME2D,
|
||||
COLOR1,
|
||||
COLOR3,
|
||||
COLOR4,
|
||||
RECT2D,
|
||||
AABOX2D = RECT2D,
|
||||
AABOX,
|
||||
ARRAY,
|
||||
TABLE};
|
||||
|
||||
/** Base class for all AnyVal exceptions.*/
|
||||
class Exception {
|
||||
public:
|
||||
virtual ~Exception() {}
|
||||
};
|
||||
|
||||
/** Thrown when an inappropriate operation is performed (e.g., operator[] on a number) */
|
||||
class WrongType : public Exception {
|
||||
public:
|
||||
Type expected;
|
||||
Type actual;
|
||||
WrongType() : expected(NIL), actual(NIL) {}
|
||||
WrongType(Type e, Type a) : expected(e), actual(a) {}
|
||||
};
|
||||
|
||||
/** Thrown by operator[] when a key is not present. */
|
||||
class KeyNotFound : public Exception {
|
||||
public:
|
||||
std::string key;
|
||||
KeyNotFound() {}
|
||||
KeyNotFound(const std::string& k) : key(k) {}
|
||||
};
|
||||
|
||||
class IndexOutOfBounds : public Exception {
|
||||
public:
|
||||
int index;
|
||||
int size;
|
||||
IndexOutOfBounds() : index(0), size(0) {}
|
||||
IndexOutOfBounds(int i, int s) : index(i), size(s) {}
|
||||
};
|
||||
|
||||
/** Thrown when deserialize() when the input is incorrectly formatted. */
|
||||
class CorruptText : public Exception {
|
||||
public:
|
||||
std::string message;
|
||||
|
||||
/** Token where the problem occurred.*/
|
||||
G3D::Token token;
|
||||
|
||||
CorruptText() {}
|
||||
CorruptText(const std::string& s, const G3D::Token& t) : message(s), token(t) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
Type m_type;
|
||||
void* m_value;
|
||||
|
||||
/** For table and array types, *m_value is shared between multiple
|
||||
instances. Mutation is allowed only if the reference count is
|
||||
exactly 1, otherwise the mutating instance must copy the
|
||||
value. This is not used for other types.
|
||||
*/
|
||||
int* m_referenceCount;
|
||||
|
||||
/** Decrements the reference count (if there is one). If the
|
||||
reference count is zero or does not exist. Calls delete on @a
|
||||
m_value and sets it to NULL.
|
||||
*/
|
||||
void deleteValue();
|
||||
|
||||
/** Returns a copy of the value. */
|
||||
void* copyValue() const;
|
||||
|
||||
/** Assumes isSharedType. Ensures that this has a unique reference */
|
||||
void makeMutable();
|
||||
|
||||
/** True if this is a shared value between multiple instances. */
|
||||
inline bool isShared() const {
|
||||
return m_referenceCount && (*m_referenceCount > 1);
|
||||
}
|
||||
|
||||
/** True when m_value is a double pointer */
|
||||
inline bool isSharedType() const {
|
||||
return (m_type == TABLE) || (m_type == ARRAY);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
AnyVal();
|
||||
|
||||
/** Deserialize */
|
||||
explicit AnyVal(G3D::TextInput& t);
|
||||
|
||||
static AnyVal fromFile(const std::string& filename);
|
||||
|
||||
void load(const std::string& filename);
|
||||
|
||||
void save(const std::string& filename) const;
|
||||
|
||||
///** Deserialize */
|
||||
//explicit AnyVal(G3D::BinaryInput& t);
|
||||
|
||||
/** Construct a number */
|
||||
AnyVal(double);
|
||||
AnyVal(int);
|
||||
|
||||
// Explicit to avoid ambiguity with the 'double' constructor
|
||||
// when an integer type is constructed
|
||||
AnyVal(bool);
|
||||
AnyVal(const G3D::Vector2&);
|
||||
AnyVal(const G3D::Vector3&);
|
||||
AnyVal(const G3D::Vector4&);
|
||||
|
||||
AnyVal(const G3D::Color1&);
|
||||
AnyVal(const G3D::Color3&);
|
||||
AnyVal(const G3D::Color4&);
|
||||
|
||||
AnyVal(const std::string&);
|
||||
AnyVal(const char*);
|
||||
|
||||
AnyVal(const G3D::Quat&);
|
||||
|
||||
AnyVal(const G3D::Rect2D&);
|
||||
AnyVal(const G3D::AABox&);
|
||||
|
||||
AnyVal(const G3D::CoordinateFrame&);
|
||||
AnyVal(const G3D::Matrix2&);
|
||||
AnyVal(const G3D::Matrix3&);
|
||||
AnyVal(const G3D::Matrix4&);
|
||||
|
||||
AnyVal(const AnyVal&);
|
||||
|
||||
AnyVal(Type arrayOrTable);
|
||||
|
||||
AnyVal& operator=(const AnyVal&);
|
||||
|
||||
/** Frees the underlying storage */
|
||||
~AnyVal();
|
||||
|
||||
Type type() const;
|
||||
|
||||
bool isNil() const {
|
||||
return type() == NIL;
|
||||
}
|
||||
|
||||
void serialize(G3D::TextOutput& t) const;
|
||||
//void serialize(G3D::BinaryOutput& t) const;
|
||||
void deserialize(G3D::TextInput& t);
|
||||
//void deserialize(G3D::BinaryInput& t);
|
||||
|
||||
/** Array dereference. If the index is out of bounds, IndexOutOfBounds is thrown */
|
||||
const AnyVal& operator[](int) const;
|
||||
|
||||
/** Extend this array by one element. */
|
||||
void append(const AnyVal&);
|
||||
|
||||
/** If the index is out of bounds, the array is resized. If the index is negative,
|
||||
IndexOutOfBounds is thrown.*/
|
||||
AnyVal& operator[](int);
|
||||
|
||||
/** If @a i is out of bounds or this is not an ARRAY, defaultVal is returned.*/
|
||||
const AnyVal& get(int i, const AnyVal& defaultVal) const;
|
||||
|
||||
/** If out of bounds, IndexOutOfBounds is thrown. */
|
||||
const AnyVal& get(int i) const;
|
||||
|
||||
/** Returns defaultVal if this is not a TABLE or the key is not found. */
|
||||
const AnyVal& get(const std::string& key, const AnyVal& defaultVal) const;
|
||||
|
||||
/** Throws KeyNotFound exception if the key is not present.*/
|
||||
const AnyVal& get(const std::string& key) const;
|
||||
|
||||
/** Table reference */
|
||||
const AnyVal& operator[](const std::string&) const;
|
||||
|
||||
/** Table reference. If the element does not exist, it is created. */
|
||||
AnyVal& operator[](const std::string&);
|
||||
|
||||
/** Table reference */
|
||||
const AnyVal& operator[](const char*) const;
|
||||
|
||||
/** Table reference. If the element does not exist, it is created. */
|
||||
AnyVal& operator[](const char*);
|
||||
|
||||
/** If this value is not a number throws a WrongType exception. */
|
||||
double number() const;
|
||||
|
||||
/** If this value is not a number, returns defaultVal. */
|
||||
double number(double defaultVal) const;
|
||||
|
||||
operator double () const {
|
||||
return number();
|
||||
}
|
||||
|
||||
operator float () const {
|
||||
return (float)number();
|
||||
}
|
||||
|
||||
bool boolean() const;
|
||||
bool boolean(bool b) const;
|
||||
|
||||
operator bool() const {
|
||||
return boolean();
|
||||
}
|
||||
|
||||
const std::string& string() const;
|
||||
const std::string& string(const std::string& defaultVal) const;
|
||||
|
||||
operator const std::string& () const {
|
||||
return string();
|
||||
}
|
||||
|
||||
const G3D::Rect2D& rect2D() const;
|
||||
const G3D::Rect2D& rect2D(const G3D::Rect2D& defaultVal) const;
|
||||
|
||||
operator const Rect2D& () const {
|
||||
return rect2D();
|
||||
}
|
||||
|
||||
const G3D::AABox& aabox() const;
|
||||
const G3D::AABox& aabox(const G3D::AABox& defaultVal) const;
|
||||
|
||||
operator const AABox& () const {
|
||||
return aabox();
|
||||
}
|
||||
|
||||
const G3D::Vector2& vector2() const;
|
||||
const G3D::Vector2& vector2(const G3D::Vector2& defaultVal) const;
|
||||
|
||||
operator const Vector2& () const {
|
||||
return vector2();
|
||||
}
|
||||
|
||||
const G3D::Vector3& vector3() const;
|
||||
const G3D::Vector3& vector3(const G3D::Vector3& defaultVal) const;
|
||||
|
||||
operator const Vector3& () {
|
||||
return vector3();
|
||||
}
|
||||
|
||||
const G3D::Vector4& vector4() const;
|
||||
const G3D::Vector4& vector4(const G3D::Vector4& defaultVal) const;
|
||||
|
||||
operator const Vector4& () const {
|
||||
return vector4();
|
||||
}
|
||||
|
||||
const G3D::Color1& color1() const;
|
||||
const G3D::Color1& color1(const G3D::Color1& defaultVal) const;
|
||||
|
||||
const G3D::Color3& color3() const;
|
||||
const G3D::Color3& color3(const G3D::Color3& defaultVal) const;
|
||||
|
||||
operator const Color3& () const {
|
||||
return color3();
|
||||
}
|
||||
|
||||
const G3D::Color4& color4() const;
|
||||
const G3D::Color4& color4(const G3D::Color4& defaultVal) const;
|
||||
|
||||
operator const Color4& () const {
|
||||
return color4();
|
||||
}
|
||||
|
||||
const G3D::CoordinateFrame& coordinateFrame() const;
|
||||
const G3D::CoordinateFrame& coordinateFrame(const G3D::CoordinateFrame& defaultVal) const;
|
||||
|
||||
operator const CoordinateFrame& () const {
|
||||
return coordinateFrame();
|
||||
}
|
||||
|
||||
const G3D::Matrix2& matrix2() const;
|
||||
const G3D::Matrix2& matrix2(const G3D::Matrix2& defaultVal) const;
|
||||
|
||||
operator const Matrix2& () const {
|
||||
return matrix2();
|
||||
}
|
||||
|
||||
const G3D::Matrix3& matrix3() const;
|
||||
const G3D::Matrix3& matrix3(const G3D::Matrix3& defaultVal) const;
|
||||
|
||||
operator const Matrix3& () const {
|
||||
return matrix3();
|
||||
}
|
||||
|
||||
const G3D::Matrix4& matrix4() const;
|
||||
const G3D::Matrix4& matrix4(const G3D::Matrix4& defaultVal) const;
|
||||
|
||||
operator const Matrix4& () const {
|
||||
return matrix4();
|
||||
}
|
||||
|
||||
const G3D::Quat& quat() const;
|
||||
const G3D::Quat& quat(const G3D::Quat& defaultVal) const;
|
||||
|
||||
operator const Quat& () const {
|
||||
return quat();
|
||||
}
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** Number of elements for an array or table.*/
|
||||
int size() const;
|
||||
|
||||
/** For a table, returns the keys. */
|
||||
void getKeys(G3D::Array<std::string>&) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
93
dep/g3dlite/include/G3D/AreaMemoryManager.h
Normal file
93
dep/g3dlite/include/G3D/AreaMemoryManager.h
Normal file
@@ -0,0 +1,93 @@
|
||||
/**
|
||||
\file AreaMemoryManager.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2009-01-20
|
||||
\edited 2010-10-29
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_AreaMemoryManager_h
|
||||
#define G3D_AreaMemoryManager_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief Allocates memory in large blocks and then frees it as an area.
|
||||
|
||||
Useful for ensuring cache coherence and for reducing the time cost of
|
||||
multiple allocations and deallocations.
|
||||
|
||||
<b>Not threadsafe</b>
|
||||
*/
|
||||
class AreaMemoryManager : public MemoryManager {
|
||||
private:
|
||||
|
||||
class Buffer {
|
||||
private:
|
||||
uint8* m_first;
|
||||
size_t m_size;
|
||||
size_t m_used;
|
||||
|
||||
public:
|
||||
|
||||
Buffer(size_t size);
|
||||
|
||||
~Buffer();
|
||||
|
||||
/** Returns NULL if out of space */
|
||||
void* alloc(size_t s);
|
||||
};
|
||||
|
||||
size_t m_sizeHint;
|
||||
|
||||
/** The underlying array is stored in regular MemoryManager heap memory */
|
||||
Array<Buffer*> m_bufferArray;
|
||||
|
||||
AreaMemoryManager(size_t sizeHint);
|
||||
|
||||
public:
|
||||
|
||||
typedef shared_ptr<AreaMemoryManager> Ref;
|
||||
|
||||
/**
|
||||
\param sizeHint Total amount of memory expected to be allocated.
|
||||
The allocator will allocate memory from the system in increments
|
||||
of this size.
|
||||
*/
|
||||
static AreaMemoryManager::Ref create(size_t sizeHint = 10 * 1024 * 1024);
|
||||
|
||||
/** Invokes deallocateAll. */
|
||||
~AreaMemoryManager();
|
||||
|
||||
size_t bytesAllocated() const;
|
||||
|
||||
/** Allocates memory out of the buffer pool.
|
||||
@param s must be no larger than sizeHint */
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
/** Ignored. */
|
||||
virtual void free(void* x);
|
||||
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** Deletes all previously allocated memory. Because delete is not
|
||||
invoked on objects in this memory, it is not safe to simply
|
||||
free memory containing C++ objects that expect their destructors
|
||||
to be called. */
|
||||
void deallocateAll();
|
||||
};
|
||||
|
||||
typedef AreaMemoryManager CoherentAllocator;
|
||||
}
|
||||
|
||||
#endif
|
||||
1466
dep/g3dlite/include/G3D/Array.h
Normal file
1466
dep/g3dlite/include/G3D/Array.h
Normal file
File diff suppressed because it is too large
Load Diff
164
dep/g3dlite/include/G3D/AtomicInt32.h
Normal file
164
dep/g3dlite/include/G3D/AtomicInt32.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
@file AtomicInt32.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-09-01
|
||||
@edited 2006-06-21
|
||||
*/
|
||||
#ifndef G3D_ATOMICINT32_H
|
||||
#define G3D_ATOMICINT32_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
#if defined(G3D_OSX)
|
||||
# include <libkern/OSAtomic.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An integer that may safely be used on different threads without
|
||||
external locking.
|
||||
|
||||
On Win32, Linux, FreeBSD, and Mac OS X this is implemented without locks.
|
||||
|
||||
<B>BETA API</B> This is unsupported and may change
|
||||
*/
|
||||
class AtomicInt32 {
|
||||
private:
|
||||
# if defined(G3D_WINDOWS)
|
||||
volatile long m_value;
|
||||
# elif defined(G3D_OSX)
|
||||
int32_t m_value;
|
||||
# else
|
||||
volatile int32 m_value;
|
||||
# endif
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/** Initial value is undefined. */
|
||||
AtomicInt32() {}
|
||||
|
||||
/** Atomic set */
|
||||
explicit AtomicInt32(const int32 x) {
|
||||
m_value = x;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
AtomicInt32(const AtomicInt32& x) {
|
||||
m_value = x.m_value;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
const AtomicInt32& operator=(const int32 x) {
|
||||
m_value = x;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Atomic set */
|
||||
void operator=(const AtomicInt32& x) {
|
||||
m_value = x.m_value;
|
||||
}
|
||||
|
||||
/** Returns the current value */
|
||||
int32 value() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
/** Returns the old value, before the add. */
|
||||
int32 add(const int32 x) {
|
||||
# if defined(G3D_WINDOWS)
|
||||
|
||||
return InterlockedExchangeAdd(&m_value, x);
|
||||
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
|
||||
int32 old;
|
||||
asm volatile ("lock; xaddl %0,%1"
|
||||
: "=r"(old), "=m"(m_value) /* outputs */
|
||||
: "0"(x), "m"(m_value) /* inputs */
|
||||
: "memory", "cc");
|
||||
return old;
|
||||
|
||||
# elif defined(G3D_OSX)
|
||||
|
||||
int32 old = m_value;
|
||||
OSAtomicAdd32(x, &m_value);
|
||||
return old;
|
||||
|
||||
# endif
|
||||
}
|
||||
|
||||
/** Returns old value. */
|
||||
int32 sub(const int32 x) {
|
||||
return add(-x);
|
||||
}
|
||||
|
||||
void increment() {
|
||||
# if defined(G3D_WINDOWS)
|
||||
// Note: returns the newly incremented value
|
||||
InterlockedIncrement(&m_value);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
add(1);
|
||||
# elif defined(G3D_OSX)
|
||||
// Note: returns the newly incremented value
|
||||
OSAtomicIncrement32(&m_value);
|
||||
# endif
|
||||
}
|
||||
|
||||
/** Returns zero if the result is zero after decrement, non-zero otherwise.*/
|
||||
int32 decrement() {
|
||||
# if defined(G3D_WINDOWS)
|
||||
// Note: returns the newly decremented value
|
||||
return InterlockedDecrement(&m_value);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
|
||||
unsigned char nz;
|
||||
|
||||
asm volatile ("lock; decl %1;\n\t"
|
||||
"setnz %%al"
|
||||
: "=a" (nz)
|
||||
: "m" (m_value)
|
||||
: "memory", "cc");
|
||||
return nz;
|
||||
# elif defined(G3D_OSX)
|
||||
// Note: returns the newly decremented value
|
||||
return OSAtomicDecrement32(&m_value);
|
||||
# endif
|
||||
}
|
||||
|
||||
|
||||
/** Atomic test-and-set: if <code>*this == comperand</code> then <code>*this := exchange</code> else do nothing.
|
||||
In both cases, returns the old value of <code>*this</code>.
|
||||
|
||||
Performs an atomic comparison of this with the Comperand value.
|
||||
If this is equal to the Comperand value, the Exchange value is stored in this.
|
||||
Otherwise, no operation is performed.
|
||||
|
||||
Under VC6 the sign bit may be lost.
|
||||
*/
|
||||
int32 compareAndSet(const int32 comperand, const int32 exchange) {
|
||||
# if defined(G3D_WINDOWS)
|
||||
return InterlockedCompareExchange(&m_value, exchange, comperand);
|
||||
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD) || defined(G3D_OSX)
|
||||
// Based on Apache Portable Runtime
|
||||
// http://koders.com/c/fid3B6631EE94542CDBAA03E822CA780CBA1B024822.aspx
|
||||
int32 ret;
|
||||
asm volatile ("lock; cmpxchgl %1, %2"
|
||||
: "=a" (ret)
|
||||
: "r" (exchange), "m" (m_value), "0"(comperand)
|
||||
: "memory", "cc");
|
||||
return ret;
|
||||
|
||||
// Note that OSAtomicCompareAndSwap32 does not return a useful value for us
|
||||
// so it can't satisfy the cmpxchgl contract.
|
||||
# endif
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
92
dep/g3dlite/include/G3D/BIN.h
Normal file
92
dep/g3dlite/include/G3D/BIN.h
Normal file
@@ -0,0 +1,92 @@
|
||||
#ifndef G3D_BIN_h
|
||||
#define G3D_BIN_h
|
||||
|
||||
#define _BIT(N, K) (((N >> (3*K)) & 1) << K)
|
||||
|
||||
#define _OCT_CODED_BIN(N) \
|
||||
(_BIT(N, 0) | _BIT(N, 1) | _BIT(N, 2) | _BIT(N, 3) | \
|
||||
_BIT(N, 4) | _BIT(N, 5) | _BIT(N, 6) | _BIT(N, 7) | \
|
||||
_BIT(N, | _BIT(N, 9) | _BIT(N, 10))
|
||||
|
||||
/**
|
||||
\def BIN11()
|
||||
|
||||
\brief Create a binary constant up to 11 digits long at compile time.
|
||||
|
||||
\code
|
||||
int i = BIN(01100101001)
|
||||
\endcode
|
||||
|
||||
\cite By Kaz Kylheku http://www.velocityreviews.com/forums/t620780-mathew-hendrys-macro-for-binary-integer-literals.html
|
||||
\sa BIN8(), BIN11(), BIN16(), BIN32()
|
||||
*/
|
||||
#define BIN11(N) _OCT_CODED_BIN(0 ## N ## UL)
|
||||
|
||||
|
||||
|
||||
/* turn a numeric literal into a hex constant
|
||||
(avoids problems with leading zeroes)
|
||||
8-bit constants max value 0x11111111, always fits in unsigned long
|
||||
*/
|
||||
#define HEX__(n) 0x##n##LU
|
||||
|
||||
/* 8-bit conversion function */
|
||||
#define B8__(x) ((x&0x0000000FLU)?1:0) \
|
||||
+((x&0x000000F0LU)?2:0) \
|
||||
+((x&0x00000F00LU)?4:0) \
|
||||
+((x&0x0000F000LU)?8:0) \
|
||||
+((x&0x000F0000LU)?16:0) \
|
||||
+((x&0x00F00000LU)?32:0) \
|
||||
+((x&0x0F000000LU)?64:0) \
|
||||
+((x&0xF0000000LU)?128:0)
|
||||
|
||||
/**
|
||||
\def BIN8()
|
||||
\brief Generate a 16-bit constant in binary notation, in 8-bit strings.
|
||||
|
||||
The most significant byte is first.
|
||||
|
||||
\code
|
||||
unsigned int i = BIN8(01010101); // 85
|
||||
\endcode
|
||||
|
||||
\cite Tom Torfs http://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f
|
||||
\sa BIN8(), BIN11(), BIN16(), BIN32()
|
||||
*/
|
||||
#define BIN8(d) ((unsigned char)B8__(HEX__(d)))
|
||||
|
||||
/** \def BIN16()
|
||||
\brief Generate a 16-bit constant in binary notation, in 8-bit strings.
|
||||
|
||||
The most significant byte is first.
|
||||
|
||||
\code
|
||||
unsigned int i = BIN16(10101010,01010101); // 43605
|
||||
\endcode
|
||||
|
||||
\cite Tom Torfs http://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f
|
||||
\sa BIN8(), BIN11(), BIN16(), BIN32()
|
||||
*/
|
||||
#define BIN16(dmsb, dlsb) (((unsigned short)BIN8(dmsb) << 8) + BIN8(dlsb))
|
||||
|
||||
|
||||
/**
|
||||
\def BIN32()
|
||||
\brief Generate a 32-bit constant in binary notation, in 8-bit strings.
|
||||
|
||||
The most significant byte is first.
|
||||
|
||||
\code
|
||||
unsigned int = BIN32(10000000,11111111,10101010,01010101); // 2164238933
|
||||
\endcode
|
||||
|
||||
\cite Tom Torfs http://groups.google.com/group/comp.arch.embedded/msg/9d430b6d3da12c8f
|
||||
\sa BIN8(), BIN11(), BIN16(), BIN32()
|
||||
*/
|
||||
#define BIN32(dmsb,db2,db3,dlsb) \
|
||||
(((unsigned long)BIN8(dmsb) << 24) + \
|
||||
((unsigned long)BIN8(db2) << 16) + \
|
||||
((unsigned long)BIN8(db3) << 8) + \
|
||||
BIN8(dlsb))
|
||||
|
||||
#endif
|
||||
140
dep/g3dlite/include/G3D/BinaryFormat.h
Normal file
140
dep/g3dlite/include/G3D/BinaryFormat.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/**
|
||||
@file BinaryFormat.h
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@author 2005-06-03
|
||||
@edited 2005-06-03
|
||||
|
||||
Copyright 2000-2005, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BINARYFORMAT_H
|
||||
#define G3D_BINARYFORMAT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector2int16;
|
||||
class Vector3;
|
||||
class Vector3int16;
|
||||
class Vector4;
|
||||
class Vector4int16;
|
||||
class Color3;
|
||||
class Color3uint8;
|
||||
class Color4;
|
||||
class Color4uint8;
|
||||
|
||||
/**
|
||||
Some values like float16 and int128 have no current CPU data structure that implements them but are useful
|
||||
for file formats and for GPUs.
|
||||
|
||||
CHUNK_BINFMT data follows the protocol.
|
||||
*/
|
||||
// Must be packed int 16 bits for the chunk reader
|
||||
// We can't name these just "INT8" etc. because some libraries #define names like that
|
||||
enum BinaryFormat {
|
||||
FIRST_BINFMT = 1000,
|
||||
|
||||
BOOL8_BINFMT,
|
||||
UINT8_BINFMT, INT8_BINFMT, UINT16_BINFMT, INT16_BINFMT, UINT32_BINFMT, INT32_BINFMT, UINT64_BINFMT, INT64_BINFMT, UINT128_BINFMT, INT128_BINFMT,
|
||||
FLOAT16_BINFMT, FLOAT32_BINFMT, FLOAT64_BINFMT,
|
||||
VECTOR2_BINFMT, VECTOR2INT16_BINFMT,
|
||||
VECTOR3_BINFMT, VECTOR3INT16_BINFMT,
|
||||
VECTOR4_BINFMT, VECTOR4INT16_BINFMT,
|
||||
COLOR3_BINFMT, COLOR3UINT8_BINFMT, COLOR3INT16_BINFMT,
|
||||
COLOR4_BINFMT, COLOR4UINT8_BINFMT, COLOR4INT16_BINFMT,
|
||||
STRING_BINFMT, STRINGEVEN_BINFMT, STRING8_BINFMT, STRING16_BINFMT, STRING32_BINFMT,
|
||||
|
||||
CHUNK_BINFMT,
|
||||
|
||||
CUSTOM_BINFMT,
|
||||
|
||||
LAST_BINFMT
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/** A macro that maps G3D types to format constants.
|
||||
(e.g. binaryFormatOf(Vector3) == VECTOR3_BINFMT).
|
||||
*/
|
||||
// This implementation is designed to meet the following constraints:
|
||||
// 1. Work around the many MSVC++ partial template bugs
|
||||
// 2. Work for primitive types (e.g. int)
|
||||
#define binaryFormatOf(T) (G3D::_internal::_BinaryFormat<T>::x())
|
||||
|
||||
namespace G3D {
|
||||
namespace _internal {
|
||||
|
||||
|
||||
template<class T> class _BinaryFormat {
|
||||
public:
|
||||
static BinaryFormat x() {
|
||||
return CUSTOM_BINFMT;
|
||||
}
|
||||
};
|
||||
}}
|
||||
|
||||
|
||||
/**
|
||||
Macro to declare the underlying format (as will be returned by glFormatOf)
|
||||
of a type. For example,
|
||||
|
||||
<PRE>
|
||||
DECLARE_BINARYFORMATOF(Vector4, VECTOR4_BINFMT)
|
||||
</PRE>
|
||||
|
||||
Use this so you can make vertex arrays of your own classes and not just
|
||||
the standard ones.
|
||||
*/
|
||||
#define DECLARE_BINARYFORMATOF(CType, EnumType) \
|
||||
namespace G3D { \
|
||||
namespace _internal { \
|
||||
template<> class _BinaryFormat<CType> { \
|
||||
public: \
|
||||
static BinaryFormat x() { \
|
||||
return EnumType; \
|
||||
} \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
DECLARE_BINARYFORMATOF( bool, BOOL8_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( uint8, UINT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int8, INT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint16, UINT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int16, INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint32, UINT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int32, INT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( uint64, UINT64_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( int64, INT64_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( float32, FLOAT32_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( float64, FLOAT64_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( Vector2, VECTOR2_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector2int16, VECTOR2INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector3, VECTOR3_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector3int16, VECTOR3INT16_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector4, VECTOR4_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Vector4int16, VECTOR4INT16_BINFMT )
|
||||
|
||||
DECLARE_BINARYFORMATOF( Color3, COLOR3_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color3uint8, COLOR3UINT8_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color4, COLOR4_BINFMT )
|
||||
DECLARE_BINARYFORMATOF( Color4uint8, COLOR4UINT8_BINFMT )
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Returns -1 if the format is custom, otherwise the byte size
|
||||
of a single element in this format.*/
|
||||
int32 byteSize(BinaryFormat f);
|
||||
|
||||
|
||||
} //G3D
|
||||
|
||||
#endif
|
||||
458
dep/g3dlite/include/G3D/BinaryInput.h
Normal file
458
dep/g3dlite/include/G3D/BinaryInput.h
Normal file
@@ -0,0 +1,458 @@
|
||||
/**
|
||||
\file G3D/BinaryInput.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-08-09
|
||||
\edited 2013-01-03
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BinaryInput_h
|
||||
#define G3D_BinaryInput_h
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning(push)
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/unorm8.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#if defined(G3D_WINDOWS) || defined(G3D_LINUX)
|
||||
// Allow writing of integers to non-word aligned locations.
|
||||
// This is legal on x86, but not on other platforms.
|
||||
#define G3D_ALLOW_UNALIGNED_WRITES
|
||||
#endif
|
||||
|
||||
/**
|
||||
Sequential or random access byte-order independent binary file access.
|
||||
Files compressed with zlib and beginning with an unsigned 32-bit int
|
||||
size are transparently decompressed when the compressed = true flag is
|
||||
specified to the constructor.
|
||||
|
||||
For every readX method there are also versions that operate on a whole
|
||||
Array, std::vector, or C-array. e.g. readFloat32(Array<float32>& array, n)
|
||||
These methods resize the array or std::vector to the appropriate size
|
||||
before reading. For a C-array, they require the pointer to reference
|
||||
a memory block at least large enough to hold <I>n</I> elements.
|
||||
|
||||
Most classes define serialize/deserialize methods that use BinaryInput,
|
||||
BinaryOutput, TextInput, and TextOutput. There are text serializer
|
||||
functions for primitive types (e.g. int, std::string, float, double) but not
|
||||
binary serializers-- you <B>must</b> call the BinaryInput::readInt32 or
|
||||
other appropriate function. This is because it would be very hard to
|
||||
debug the error sequence: <CODE>serialize(1.0, bo); ... float f; deserialize(f, bi);</CODE>
|
||||
in which a double is serialized and then deserialized as a float.
|
||||
*/
|
||||
class BinaryInput {
|
||||
private:
|
||||
|
||||
// The initial buffer will be no larger than this, but
|
||||
// may grow if a large memory read occurs. 750 MB
|
||||
static const int64
|
||||
INITIAL_BUFFER_LENGTH =
|
||||
#ifdef G3D_64BIT
|
||||
5000000000L // 5 GB
|
||||
#else
|
||||
750000000 // 750 MB
|
||||
#endif
|
||||
;
|
||||
|
||||
/**
|
||||
is the file big or little endian
|
||||
*/
|
||||
G3DEndian m_fileEndian;
|
||||
std::string m_filename;
|
||||
|
||||
bool m_swapBytes;
|
||||
|
||||
/** Next position to read from in bitString during readBits. */
|
||||
int m_bitPos;
|
||||
|
||||
/** Bits currently being read by readBits.
|
||||
Contains at most 8 (low) bits. Note that
|
||||
beginBits/readBits actually consumes one extra byte, which
|
||||
will be restored by writeBits.*/
|
||||
uint32 m_bitString;
|
||||
|
||||
/** 1 when between beginBits and endBits, 0 otherwise. */
|
||||
int m_beginEndBits;
|
||||
|
||||
/** When operating on huge files, we cannot load the whole file into memory.
|
||||
This is the file position to which buffer[0] corresponds.
|
||||
Even 32-bit code can load 64-bit files in chunks, so this is not size_t
|
||||
*/
|
||||
int64 m_alreadyRead;
|
||||
|
||||
/**
|
||||
Length of the entire file, in bytes.
|
||||
For the length of the buffer, see bufferLength
|
||||
*/
|
||||
int64 m_length;
|
||||
|
||||
/** Length of the array referenced by buffer. May go past the end of the file!*/
|
||||
int64 m_bufferLength;
|
||||
uint8* m_buffer;
|
||||
|
||||
/**
|
||||
Next byte in file, relative to buffer.
|
||||
*/
|
||||
int64 m_pos;
|
||||
|
||||
/**
|
||||
When true, the buffer is freed in the destructor.
|
||||
*/
|
||||
bool m_freeBuffer;
|
||||
|
||||
/** Ensures that we are able to read at least minLength from startPosition (relative
|
||||
to start of file). */
|
||||
void loadIntoMemory(int64 startPosition, int64 minLength = 0);
|
||||
|
||||
/** Verifies that at least this number of bytes can be read.*/
|
||||
void prepareToRead(int64 nbytes);
|
||||
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
BinaryInput(const BinaryInput&);
|
||||
BinaryInput& operator=(const BinaryInput&);
|
||||
bool operator==(const BinaryInput&);
|
||||
|
||||
/** Buffer is compressed; replace it with a decompressed version */
|
||||
void decompress();
|
||||
public:
|
||||
|
||||
/** false, constant to use with the copyMemory option */
|
||||
static const bool NO_COPY;
|
||||
|
||||
/**
|
||||
If the file cannot be opened, a zero length buffer is presented.
|
||||
Automatically opens files that are inside zipfiles.
|
||||
|
||||
@param compressed Set to true if and only if the file was
|
||||
compressed using BinaryOutput's zlib compression. This has
|
||||
nothing to do with whether the input is in a zipfile.
|
||||
*/
|
||||
BinaryInput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian,
|
||||
bool compressed = false);
|
||||
|
||||
/**
|
||||
Creates input stream from an in memory source.
|
||||
Unless you specify copyMemory = false, the data is copied
|
||||
from the pointer, so you may deallocate it as soon as the
|
||||
object is constructed. It is an error to specify copyMemory = false
|
||||
and compressed = true.
|
||||
|
||||
To decompress part of a file, you can follow the following paradigm:
|
||||
|
||||
\htmlonly
|
||||
<PRE>
|
||||
BinaryInput master(...);
|
||||
|
||||
// read from master to point where compressed data exists.
|
||||
|
||||
BinaryInput subset(master.getCArray() + master.getPosition(),
|
||||
master.length() - master.getPosition(),
|
||||
master.endian(), true, true);
|
||||
|
||||
// Now read from subset (it is ok for master to go out of scope)
|
||||
</PRE>
|
||||
\endhtmlonly
|
||||
*/
|
||||
BinaryInput(
|
||||
const uint8* data,
|
||||
int64 dataLen,
|
||||
G3DEndian dataEndian,
|
||||
bool compressed = false,
|
||||
bool copyMemory = true);
|
||||
|
||||
virtual ~BinaryInput();
|
||||
|
||||
/** Change the endian-ness of the file. This only changes the
|
||||
interpretation of the file for future read calls; the
|
||||
underlying data is unmodified.*/
|
||||
void setEndian(G3DEndian endian);
|
||||
|
||||
G3DEndian endian() const {
|
||||
return m_fileEndian;
|
||||
}
|
||||
|
||||
std::string getFilename() const {
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode. [] are relative to
|
||||
the start of the file, not the current position.
|
||||
Seeks to the new position before reading (and leaves
|
||||
that as the current position)
|
||||
*/
|
||||
uint8 operator[](int64 n) {
|
||||
setPosition(n);
|
||||
return readUInt8();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the length of the file in bytes.
|
||||
*/
|
||||
int64 getLength() const {
|
||||
return m_length;
|
||||
}
|
||||
|
||||
int64 size() const {
|
||||
return getLength();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current byte position in the file,
|
||||
where 0 is the beginning and getLength() - 1 is the end.
|
||||
*/
|
||||
int64 getPosition() const {
|
||||
return m_pos + m_alreadyRead;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a pointer to the internal memory buffer.
|
||||
May throw an exception for huge files.
|
||||
*/
|
||||
const uint8* getCArray() {
|
||||
if (m_alreadyRead > 0 || m_bufferLength < m_length) {
|
||||
throw "Cannot getCArray for a huge file";
|
||||
}
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the position. Cannot set past length.
|
||||
May throw a char* when seeking backwards more than 10 MB on a huge file.
|
||||
*/
|
||||
void setPosition(int64 p) {
|
||||
debugAssertM(p <= m_length, "Read past end of file");
|
||||
m_pos = p - m_alreadyRead;
|
||||
if ((m_pos < 0) || (m_pos > m_bufferLength)) {
|
||||
loadIntoMemory(m_pos + m_alreadyRead);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Goes back to the beginning of the file.
|
||||
*/
|
||||
void reset() {
|
||||
setPosition(0);
|
||||
}
|
||||
|
||||
void readBytes(void* bytes, int64 n);
|
||||
|
||||
int8 readInt8() {
|
||||
prepareToRead(1);
|
||||
return m_buffer[m_pos++];
|
||||
}
|
||||
|
||||
bool readBool8() {
|
||||
return (readInt8() != 0);
|
||||
}
|
||||
|
||||
uint8 readUInt8() {
|
||||
prepareToRead(1);
|
||||
return ((uint8*)m_buffer)[m_pos++];
|
||||
}
|
||||
|
||||
unorm8 readUNorm8() {
|
||||
return unorm8::fromBits(readUInt8());
|
||||
}
|
||||
|
||||
uint16 readUInt16() {
|
||||
prepareToRead(2);
|
||||
|
||||
m_pos += 2;
|
||||
if (m_swapBytes) {
|
||||
uint8 out[2];
|
||||
out[0] = m_buffer[m_pos - 1];
|
||||
out[1] = m_buffer[m_pos - 2];
|
||||
return *(uint16*)out;
|
||||
} else {
|
||||
#ifdef G3D_ALLOW_UNALIGNED_WRITES
|
||||
return *(uint16*)(&m_buffer[m_pos - 2]);
|
||||
#else
|
||||
uint8 out[2];
|
||||
out[0] = m_buffer[m_pos - 2];
|
||||
out[1] = m_buffer[m_pos - 1];
|
||||
return *(uint16*)out;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int16 readInt16() {
|
||||
uint16 a = readUInt16();
|
||||
return *(int16*)&a;
|
||||
}
|
||||
|
||||
uint32 readUInt32() {
|
||||
prepareToRead(4);
|
||||
|
||||
m_pos += 4;
|
||||
if (m_swapBytes) {
|
||||
uint8 out[4];
|
||||
out[0] = m_buffer[m_pos - 1];
|
||||
out[1] = m_buffer[m_pos - 2];
|
||||
out[2] = m_buffer[m_pos - 3];
|
||||
out[3] = m_buffer[m_pos - 4];
|
||||
return *(uint32*)out;
|
||||
} else {
|
||||
#ifdef G3D_ALLOW_UNALIGNED_WRITES
|
||||
return *(uint32*)(&m_buffer[m_pos - 4]);
|
||||
#else
|
||||
uint8 out[4];
|
||||
out[0] = m_buffer[m_pos - 4];
|
||||
out[1] = m_buffer[m_pos - 3];
|
||||
out[2] = m_buffer[m_pos - 2];
|
||||
out[3] = m_buffer[m_pos - 1];
|
||||
return *(uint32*)out;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int32 readInt32() {
|
||||
uint32 a = readUInt32();
|
||||
return *(int32*)&a;
|
||||
}
|
||||
|
||||
uint64 readUInt64();
|
||||
|
||||
int64 readInt64() {
|
||||
uint64 a = readUInt64();
|
||||
return *(int64*)&a;
|
||||
}
|
||||
|
||||
float32 readFloat32() {
|
||||
union {
|
||||
uint32 a;
|
||||
float32 b;
|
||||
};
|
||||
a = readUInt32();
|
||||
return b;
|
||||
}
|
||||
|
||||
float64 readFloat64() {
|
||||
union {
|
||||
uint64 a;
|
||||
float64 b;
|
||||
};
|
||||
a = readUInt64();
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
Always consumes \a maxLength characters. Reads a string until NULL or \a maxLength characters. Does not require NULL termination.
|
||||
*/
|
||||
std::string readString(int64 maxLength);
|
||||
|
||||
/**
|
||||
Reads a string until NULL or end of file.
|
||||
*/
|
||||
std::string readString();
|
||||
|
||||
/** Read a string (which may contain NULLs) of exactly numBytes bytes, including the final terminator if there is one. If there is a NULL in the string before
|
||||
the end, then only the part up to the first NULL is returned although all bytes are read.*/
|
||||
std::string readFixedLengthString(int numBytes);
|
||||
|
||||
/**
|
||||
Reads a string until NULL, newline ("\r", "\n", "\r\n", "\n\r") or the end of the file is encountered. Consumes the newline.
|
||||
*/
|
||||
std::string readStringNewline();
|
||||
|
||||
/**
|
||||
Reads until NULL or the end of the file is encountered.
|
||||
If the string has odd length (including NULL), reads
|
||||
another byte. This is a common format for 16-bit alignment
|
||||
in files.
|
||||
*/
|
||||
std::string readStringEven();
|
||||
|
||||
/** Reads a uint32 and then calls readString(maxLength) with that value as the length. */
|
||||
std::string readString32();
|
||||
|
||||
Vector4 readVector4();
|
||||
Vector3 readVector3();
|
||||
Vector2 readVector2();
|
||||
|
||||
Color4 readColor4();
|
||||
Color3 readColor3();
|
||||
|
||||
/**
|
||||
Skips ahead n bytes.
|
||||
*/
|
||||
void skip(int64 n) {
|
||||
setPosition(m_pos + m_alreadyRead + n);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the position is not at the end of the file
|
||||
*/
|
||||
bool hasMore() const {
|
||||
return m_pos + m_alreadyRead < m_length;
|
||||
}
|
||||
|
||||
/** Prepares for bit reading via readBits. Only readBits can be
|
||||
called between beginBits and endBits without corrupting the
|
||||
data stream. */
|
||||
void beginBits();
|
||||
|
||||
/** Can only be called between beginBits and endBits */
|
||||
uint32 readBits(int numBits);
|
||||
|
||||
/** Ends bit-reading. */
|
||||
void endBits();
|
||||
|
||||
# define DECLARE_READER(ucase, lcase)\
|
||||
void read##ucase(lcase* out, int64 n);\
|
||||
void read##ucase(std::vector<lcase>& out, int64 n);\
|
||||
void read##ucase(Array<lcase>& out, int64 n);
|
||||
|
||||
DECLARE_READER(Bool8, bool)
|
||||
DECLARE_READER(UInt8, uint8)
|
||||
DECLARE_READER(Int8, int8)
|
||||
DECLARE_READER(UInt16, uint16)
|
||||
DECLARE_READER(Int16, int16)
|
||||
DECLARE_READER(UInt32, uint32)
|
||||
DECLARE_READER(Int32, int32)
|
||||
DECLARE_READER(UInt64, uint64)
|
||||
DECLARE_READER(Int64, int64)
|
||||
DECLARE_READER(Float32, float32)
|
||||
DECLARE_READER(Float64, float64)
|
||||
# undef DECLARE_READER
|
||||
};
|
||||
|
||||
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
441
dep/g3dlite/include/G3D/BinaryOutput.h
Normal file
441
dep/g3dlite/include/G3D/BinaryOutput.h
Normal file
@@ -0,0 +1,441 @@
|
||||
/**
|
||||
\file G3D/BinaryOutput.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-08-09
|
||||
\edited 2011-08-24
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BinaryOutput_h
|
||||
#define G3D_BinaryOutput_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include "G3D/unorm8.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/System.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (push)
|
||||
// Conditional is constant (wrong in inline)
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Sequential or random access byte-order independent binary file access.
|
||||
|
||||
The compress() call can be used to compress with zlib.
|
||||
|
||||
Any method call can trigger an out of memory error (thrown as char*)
|
||||
when writing to "<memory>" instead of a file.
|
||||
|
||||
Compressed writing and seeking backwards is not supported for huge files
|
||||
(i.e., BinaryOutput may have to dump the contents to disk if they
|
||||
exceed available RAM).
|
||||
*/
|
||||
class BinaryOutput {
|
||||
private:
|
||||
std::string m_filename;
|
||||
|
||||
bool m_committed;
|
||||
|
||||
/** 0 outside of beginBits...endBits, 1 inside */
|
||||
int m_beginEndBits;
|
||||
|
||||
/** The current string of bits being built up by beginBits...endBits.
|
||||
This string is treated semantically, as if the lowest bit was
|
||||
on the left and the highest was on the right.*/
|
||||
int8 m_bitString;
|
||||
|
||||
/** Position (from the lowest bit) currently used in bitString.*/
|
||||
int m_bitPos;
|
||||
|
||||
// True if the file endianess does not match the machine endian
|
||||
bool m_swapBytes;
|
||||
|
||||
G3DEndian m_fileEndian;
|
||||
|
||||
uint8* m_buffer;
|
||||
|
||||
/** Size of the elements used */
|
||||
size_t m_bufferLen;
|
||||
|
||||
/** Underlying size of memory allocaded */
|
||||
size_t m_maxBufferLen;
|
||||
|
||||
/** Next byte in file */
|
||||
int64 m_pos;
|
||||
|
||||
/** is this initialized? */
|
||||
bool m_init;
|
||||
|
||||
/** Number of bytes already written to the file. Even on 32-bit OS, this can be 64-bits*/
|
||||
int64 m_alreadyWritten;
|
||||
|
||||
bool m_ok;
|
||||
|
||||
void reserveBytesWhenOutOfMemory(size_t bytes);
|
||||
|
||||
void reallocBuffer(size_t bytes, size_t oldBufferLen);
|
||||
|
||||
/**
|
||||
Make sure at least bytes can be written, resizing if
|
||||
necessary.
|
||||
*/
|
||||
inline void reserveBytes(size_t bytes) {
|
||||
debugAssert(bytes > 0);
|
||||
size_t oldBufferLen = m_bufferLen;
|
||||
|
||||
m_bufferLen = max(m_bufferLen, (size_t)(m_pos + bytes));
|
||||
if (m_bufferLen > m_maxBufferLen) {
|
||||
reallocBuffer(bytes, oldBufferLen);
|
||||
}
|
||||
}
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
BinaryOutput(const BinaryOutput&);
|
||||
BinaryOutput& operator=(const BinaryOutput&);
|
||||
bool operator==(const BinaryOutput&);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
You must call setEndian() if you use this (memory) constructor.
|
||||
*/
|
||||
BinaryOutput();
|
||||
|
||||
/**
|
||||
Doesn't actually open the file; commit() does that.
|
||||
Use "<memory>" as the filename if you're going to commit
|
||||
to memory.
|
||||
*/
|
||||
BinaryOutput(
|
||||
const std::string& filename,
|
||||
G3DEndian fileEndian);
|
||||
|
||||
~BinaryOutput();
|
||||
|
||||
/** Compresses the data in the buffer in place,
|
||||
preceeding it with a little-endian uint32 indicating
|
||||
the uncompressed size.
|
||||
|
||||
Call immediately before commit().
|
||||
|
||||
Cannot be used for huge files (ones where the data
|
||||
was already written to disk)-- will throw char*.
|
||||
|
||||
\param level Compression level. 0 = fast, low compression; 9 = slow, high compression
|
||||
*/
|
||||
void compress(int level = 9);
|
||||
|
||||
/** True if no errors have been encountered.*/
|
||||
bool ok() const;
|
||||
|
||||
/**
|
||||
Returns a pointer to the internal memory buffer.
|
||||
*/
|
||||
inline const uint8* getCArray() const {
|
||||
return m_buffer;
|
||||
}
|
||||
|
||||
void setEndian(G3DEndian fileEndian);
|
||||
|
||||
G3DEndian endian() const {
|
||||
return m_fileEndian;
|
||||
}
|
||||
|
||||
std::string getFilename() const {
|
||||
return m_filename;
|
||||
}
|
||||
|
||||
/**
|
||||
Write the bytes to disk. It is ok to call this
|
||||
multiple times; it will just overwrite the previous file.
|
||||
|
||||
Parent directories are created as needed if they do
|
||||
not exist.
|
||||
|
||||
<B>Not</B> called from the destructor; you must call
|
||||
it yourself.
|
||||
|
||||
@param flush If true (default) the file is ready for reading when the method returns, otherwise
|
||||
the method returns immediately and writes the file in the background.
|
||||
*/
|
||||
void commit(bool flush = true);
|
||||
|
||||
/**
|
||||
Write the bytes to memory (which must be of
|
||||
at least size() bytes).
|
||||
*/
|
||||
void commit(uint8*);
|
||||
|
||||
/**
|
||||
A memory BinaryOutput may be reset so that it can be written to again
|
||||
without allocating new memory. The underlying array will not be deallocated,
|
||||
but the reset structure will act like a newly intialized one.
|
||||
*/
|
||||
void reset();
|
||||
|
||||
|
||||
inline int64 length() const {
|
||||
return m_bufferLen + m_alreadyWritten;
|
||||
}
|
||||
|
||||
inline int64 size() const {
|
||||
return length();
|
||||
}
|
||||
|
||||
/**
|
||||
Sets the length of the file to n, padding
|
||||
with 0's past the current end. Does not
|
||||
change the position of the next byte to be
|
||||
written unless n < size().
|
||||
|
||||
Throws char* when resetting a huge file to be shorter
|
||||
than its current length.
|
||||
*/
|
||||
inline void setLength(int64 n) {
|
||||
n = n - m_alreadyWritten;
|
||||
|
||||
if (n < 0) {
|
||||
throw "Cannot resize huge files to be shorter.";
|
||||
}
|
||||
|
||||
if (n < (int64)m_bufferLen) {
|
||||
m_pos = n;
|
||||
}
|
||||
if (n > (int64)m_bufferLen) {
|
||||
reserveBytes((size_t)(n - m_bufferLen));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current byte position in the file,
|
||||
where 0 is the beginning and getLength() - 1 is the end.
|
||||
*/
|
||||
inline int64 position() const {
|
||||
return m_pos + m_alreadyWritten;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Sets the position. Can set past length, in which case
|
||||
the file is padded with zeros up to one byte before the
|
||||
next to be written.
|
||||
|
||||
May throw a char* exception when seeking backwards on a huge file.
|
||||
*/
|
||||
inline void setPosition(int64 p) {
|
||||
p = p - m_alreadyWritten;
|
||||
|
||||
if (p > (int64)m_bufferLen) {
|
||||
setLength((int)(p + (int64)m_alreadyWritten));
|
||||
}
|
||||
|
||||
if (p < 0) {
|
||||
throw "Cannot seek more than 10 MB backwards on huge files.";
|
||||
}
|
||||
|
||||
m_pos = (int)p;
|
||||
}
|
||||
|
||||
|
||||
void writeBytes
|
||||
(const void* b,
|
||||
size_t count) {
|
||||
|
||||
reserveBytes(count);
|
||||
debugAssert(m_pos >= 0);
|
||||
debugAssert(m_bufferLen >= count);
|
||||
System::memcpy(m_buffer + m_pos, b, count);
|
||||
m_pos += count;
|
||||
}
|
||||
|
||||
/**
|
||||
Writes a signed 8-bit integer to the current position.
|
||||
*/
|
||||
inline void writeInt8(int8 i) {
|
||||
reserveBytes(1);
|
||||
m_buffer[m_pos] = *(uint8*)&i;
|
||||
++m_pos;
|
||||
}
|
||||
|
||||
inline void writeBool8(bool b) {
|
||||
writeInt8(b ? 1 : 0);
|
||||
}
|
||||
|
||||
inline void writeUInt8(uint8 i) {
|
||||
reserveBytes(1);
|
||||
m_buffer[m_pos] = i;
|
||||
++m_pos;
|
||||
}
|
||||
|
||||
inline void writeUNorm8(unorm8 i) {
|
||||
writeUInt8(i.bits());
|
||||
}
|
||||
|
||||
void writeUInt16(uint16 u);
|
||||
|
||||
inline void writeInt16(int16 i) {
|
||||
writeUInt16(*(uint16*)&i);
|
||||
}
|
||||
|
||||
void writeUInt32(uint32 u);
|
||||
|
||||
inline void writeInt32(int32 i) {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
writeUInt32(*(uint32*)&i);
|
||||
}
|
||||
|
||||
void writeUInt64(uint64 u);
|
||||
|
||||
inline void writeInt64(int64 i) {
|
||||
writeUInt64(*(uint64*)&i);
|
||||
}
|
||||
|
||||
inline void writeFloat32(float32 f) {
|
||||
debugAssert(m_beginEndBits == 0);
|
||||
union {
|
||||
float32 a;
|
||||
uint32 b;
|
||||
};
|
||||
a = f;
|
||||
writeUInt32(b);
|
||||
}
|
||||
|
||||
inline void writeFloat64(float64 f) {
|
||||
union {
|
||||
float64 a;
|
||||
uint64 b;
|
||||
};
|
||||
a = f;
|
||||
writeUInt64(b);
|
||||
}
|
||||
|
||||
/**
|
||||
Write a string with NULL termination.
|
||||
*/
|
||||
inline void writeString(const std::string& s) {
|
||||
writeString(s.c_str());
|
||||
}
|
||||
|
||||
/** Write a string that always consumes len bytes, truncating or padding as necessary*/
|
||||
inline void writeString(const std::string& s, int len) {
|
||||
const int pad = len - ((int)s.length() + 1);
|
||||
if (pad >= 0) {
|
||||
writeString(s.c_str());
|
||||
for (int i = 0; i < pad; ++i) {
|
||||
writeUInt8(0);
|
||||
}
|
||||
} else {
|
||||
// Truncate
|
||||
writeBytes(s.c_str(), len);
|
||||
}
|
||||
}
|
||||
|
||||
void writeString(const char* s);
|
||||
|
||||
/**
|
||||
Write a string, ensuring that the total length
|
||||
including NULL is even.
|
||||
*/
|
||||
void writeStringEven(const std::string& s) {
|
||||
writeStringEven(s.c_str());
|
||||
}
|
||||
|
||||
void writeStringEven(const char* s);
|
||||
|
||||
void writeString32(const char* s);
|
||||
|
||||
/**
|
||||
Write a NULL-terminated string with a 32-bit length field in front
|
||||
of it. The NULL character is included in the length count.
|
||||
*/
|
||||
void writeString32(const std::string& s) {
|
||||
writeString32(s.c_str());
|
||||
}
|
||||
|
||||
void writeVector4(const Vector4& v);
|
||||
|
||||
void writeVector3(const Vector3& v);
|
||||
|
||||
void writeVector2(const Vector2& v);
|
||||
|
||||
void writeColor4(const Color4& v);
|
||||
|
||||
void writeColor3(const Color3& v);
|
||||
|
||||
/**
|
||||
Skips ahead n bytes.
|
||||
*/
|
||||
inline void skip(int n) {
|
||||
if (m_pos + n > (int64)m_bufferLen) {
|
||||
setLength(m_pos + m_alreadyWritten + n);
|
||||
}
|
||||
m_pos += n;
|
||||
}
|
||||
|
||||
/** Call before a series of BinaryOutput::writeBits calls. Only writeBits
|
||||
can be called between beginBits and endBits without corrupting the stream.*/
|
||||
void beginBits();
|
||||
|
||||
/** Write numBits from bitString to the output stream. Bits are numbered from
|
||||
low to high.
|
||||
|
||||
Can only be
|
||||
called between beginBits and endBits. Bits written are semantically
|
||||
little-endian, regardless of the actual endian-ness of the system. That is,
|
||||
<CODE>writeBits(0xABCD, 16)</CODE> writes 0xCD to the first byte and
|
||||
0xAB to the second byte. However, if used with BinaryInput::readBits, the ordering
|
||||
is transparent to the caller.
|
||||
*/
|
||||
void writeBits(uint32 bitString, int numBits);
|
||||
|
||||
/** Call after a series of BinaryOutput::writeBits calls. This will
|
||||
finish out with zeros the last byte into which bits were written.*/
|
||||
void endBits();
|
||||
|
||||
|
||||
# define DECLARE_WRITER(ucase, lcase)\
|
||||
void write##ucase(const lcase* out, int n);\
|
||||
void write##ucase(const std::vector<lcase>& out, int n);\
|
||||
void write##ucase(const Array<lcase>& out, int n);
|
||||
|
||||
DECLARE_WRITER(Bool8, bool)
|
||||
DECLARE_WRITER(UInt8, uint8)
|
||||
DECLARE_WRITER(Int8, int8)
|
||||
DECLARE_WRITER(UInt16, uint16)
|
||||
DECLARE_WRITER(Int16, int16)
|
||||
DECLARE_WRITER(UInt32, uint32)
|
||||
DECLARE_WRITER(Int32, int32)
|
||||
DECLARE_WRITER(UInt64, uint64)
|
||||
DECLARE_WRITER(Int64, int64)
|
||||
DECLARE_WRITER(Float32, float32)
|
||||
DECLARE_WRITER(Float64, float64)
|
||||
# undef DECLARE_WRITER
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
20
dep/g3dlite/include/G3D/BoundsTrait.h
Normal file
20
dep/g3dlite/include/G3D/BoundsTrait.h
Normal file
@@ -0,0 +1,20 @@
|
||||
/**
|
||||
@file BoundsTrait.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-10-01
|
||||
@edited 2008-10-01
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BOUNDSTRAIT_H
|
||||
#define G3D_BOUNDSTRAIT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
template<typename Value>
|
||||
struct BoundsTrait{};
|
||||
|
||||
#endif
|
||||
|
||||
235
dep/g3dlite/include/G3D/Box.h
Normal file
235
dep/g3dlite/include/G3D/Box.h
Normal file
@@ -0,0 +1,235 @@
|
||||
/**
|
||||
\file G3D/Box.h
|
||||
|
||||
Box class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
\created 2001-06-02
|
||||
\edited 2013-04-13
|
||||
|
||||
Copyright 2000-2013, 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;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
\brief An arbitrary (oriented) 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;
|
||||
|
||||
/**
|
||||
Axes with length equal to the 4 edges that run along each of them
|
||||
*/
|
||||
Vector3 _edgeVector[3];
|
||||
|
||||
Point3 _center;
|
||||
|
||||
float _area;
|
||||
|
||||
float _volume;
|
||||
|
||||
void init(
|
||||
const Vector3& min,
|
||||
const Vector3& max);
|
||||
|
||||
public:
|
||||
|
||||
Box();
|
||||
|
||||
explicit Box(const Any& a);
|
||||
|
||||
/**
|
||||
Constructs a box from two opposite corners.
|
||||
*/
|
||||
Box(const Vector3& min,
|
||||
const Vector3& max);
|
||||
|
||||
Box(const Vector3& osMin,
|
||||
const Vector3& osMax,
|
||||
const CoordinateFrame& frame);
|
||||
|
||||
Box(class BinaryInput& b);
|
||||
|
||||
Box(const class AABox& b);
|
||||
|
||||
explicit Box(const Point3& p);
|
||||
|
||||
static Box inf();
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/**
|
||||
Returns the object to world transformation for
|
||||
this box, where the origin is the center of the 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;
|
||||
|
||||
/** \sa localFrame */
|
||||
void getLocalFrame(CoordinateFrame& frame) const;
|
||||
|
||||
Box operator*(float f) const;
|
||||
|
||||
/**
|
||||
Returns the centroid of the box.
|
||||
*/
|
||||
inline Vector3 center() const {
|
||||
return _center;
|
||||
}
|
||||
|
||||
/**
|
||||
\htmlonly
|
||||
<PRE>
|
||||
|
||||
|
||||
2--------3
|
||||
/ : /|
|
||||
/ : / |
|
||||
6--------7 |
|
||||
| : | |
|
||||
| 0....|..1
|
||||
| / | /
|
||||
|/ |/
|
||||
4--------5
|
||||
|
||||
y
|
||||
^
|
||||
|
|
||||
|-->x
|
||||
z/
|
||||
|
||||
|
||||
</PRE>
|
||||
\endhtmlonly
|
||||
*/
|
||||
Vector3 corner(int i) const;
|
||||
|
||||
/**
|
||||
Unit length.
|
||||
*/
|
||||
inline Vector3 axis(int a) const {
|
||||
debugAssert(a < 3);
|
||||
return _edgeVector[a].direction();
|
||||
}
|
||||
|
||||
/**
|
||||
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 _edgeVector[a].length();
|
||||
}
|
||||
|
||||
inline Vector3 extent() const {
|
||||
return Vector3(_edgeVector[0].length(), _edgeVector[1].length(), _edgeVector[2].length());
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the four corners of a face (0 <= f < 6).
|
||||
The corners are returned to form a clockwise quad facing outwards.
|
||||
|
||||
|
||||
|
||||
+--------+
|
||||
/ : /|
|
||||
/ : / |
|
||||
+--------+ |
|
||||
| : | |
|
||||
| +....|..+
|
||||
| / | /
|
||||
|/ |/
|
||||
+--------+
|
||||
|
||||
y
|
||||
^
|
||||
|
|
||||
|-->x
|
||||
z/
|
||||
Faces are in the following order:
|
||||
0: -Z
|
||||
1: X
|
||||
2: Z
|
||||
3: Y
|
||||
4: -X
|
||||
5: -Y
|
||||
|
||||
*/
|
||||
void getFaceCorners(
|
||||
int f,
|
||||
Vector3& v0,
|
||||
Vector3& v1,
|
||||
Vector3& v2,
|
||||
Vector3& v3) 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;
|
||||
|
||||
float area() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N = Vector3::ignore()) const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the interior (includes surface)
|
||||
*/
|
||||
Vector3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
|
||||
bool isFinite() const {
|
||||
return G3D::isFinite(_volume);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
121
dep/g3dlite/include/G3D/Box2D.h
Normal file
121
dep/g3dlite/include/G3D/Box2D.h
Normal file
@@ -0,0 +1,121 @@
|
||||
/**
|
||||
@file Box2D.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-06-02
|
||||
@edited 2008-12-27
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Box2D_h
|
||||
#define G3D_Box2D_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class CoordinateFrame;
|
||||
typedef class CoordinateFrame CFrame;
|
||||
class Rect2D;
|
||||
typedef class Rect2D AABox2D;
|
||||
|
||||
/**
|
||||
2D oriented box
|
||||
@cite http://www.flipcode.com/archives/2D_OBB_Intersection.shtml
|
||||
*/
|
||||
class Box2D {
|
||||
private:
|
||||
/** Corners of the box, where 0 is the lower left. */
|
||||
Vector2 m_corner[4];
|
||||
|
||||
/** Two edges of the box extended away from corner[0], with length
|
||||
= 1 / extentSquared */
|
||||
Vector2 m_axisin[2];
|
||||
|
||||
/** Two edges of the box extended away from corner[0], with unit length */
|
||||
Vector2 m_axis[2];
|
||||
|
||||
/** Centroid of the box */
|
||||
Vector2 m_center;
|
||||
|
||||
/** origin[a] = m_corner[0].dot(m_axisin[a]); */
|
||||
float origin[2];
|
||||
|
||||
/** Surface area */
|
||||
float m_area;
|
||||
|
||||
Vector2 m_extent;
|
||||
|
||||
/** Returns true if other overlaps one dimension of this. */
|
||||
bool overlaps1Way(const Box2D& other) const;
|
||||
|
||||
|
||||
/** Updates the axes after the m_corners move. Assumes the
|
||||
m_corners actually form a rectangle. */
|
||||
void computeAxes();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param center World-space center
|
||||
@param w Width along object-space x-axis
|
||||
@param h Height along object-space y-axis
|
||||
@param angle Counter-clockwise angle from object-space x-axis in radians
|
||||
*/
|
||||
Box2D(const Vector2& center = Vector2(0, 0), float w = 0, float h = 0, float angle = 0);
|
||||
|
||||
Box2D(const AABox2D& b);
|
||||
|
||||
Box2D(const Vector2& min, const Vector2& max);
|
||||
|
||||
/** Transform @a b by @a frame, discarding the Z components, and
|
||||
compute the new box.*/
|
||||
Box2D(const CFrame& frame, Box2D& b);
|
||||
|
||||
inline bool contains(const Vector2& v) const {
|
||||
// Take to object space:
|
||||
const Vector2& p = v - m_center;
|
||||
float x = p.dot(m_axisin[0]);
|
||||
float y = p.dot(m_axisin[1]);
|
||||
|
||||
// Must be within extent/2 on both axes in object space
|
||||
return (abs(x) <= 0.5f) && (abs(y) <= 0.5f);
|
||||
}
|
||||
|
||||
/** @brief Distance from corner(0) to the next corner along the box's local axis a. */
|
||||
inline const Vector2& extent() const {
|
||||
return m_extent;
|
||||
}
|
||||
|
||||
/** @brief Unit length vector along axis @a a */
|
||||
inline const Vector2& axis(int a) const {
|
||||
debugAssert(a == 0 || a == 1);
|
||||
return m_axis[a];
|
||||
}
|
||||
|
||||
/** @brief Surface area */
|
||||
inline float area() const {
|
||||
return m_area;
|
||||
}
|
||||
|
||||
inline const Vector2& corner(int i) const {
|
||||
debugAssert(i >=0 && i <= 3);
|
||||
return m_corner[i];
|
||||
}
|
||||
|
||||
inline const Vector2& center() const {
|
||||
return m_center;
|
||||
}
|
||||
|
||||
/** Returns true if the intersection of the boxes is non-empty. */
|
||||
inline bool overlaps(const Box2D& other) const {
|
||||
return overlaps1Way(other) && other.overlaps1Way(*this);
|
||||
}
|
||||
};
|
||||
|
||||
} // G3D
|
||||
#endif
|
||||
61
dep/g3dlite/include/G3D/BumpMapPreprocess.h
Normal file
61
dep/g3dlite/include/G3D/BumpMapPreprocess.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/**
|
||||
\file BumpMapPreprocess.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2010-01-28
|
||||
\edited 2010-01-28
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_BumpMapPreprocess_h
|
||||
#define G3D_BumpMapPreprocess_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap.
|
||||
G3D::Image::computeNormalMap().
|
||||
*/
|
||||
class BumpMapPreprocess {
|
||||
public:
|
||||
|
||||
/** If true, the elevations are box filtered after computing normals
|
||||
and before uploading, which produces better results for parallax offset mapping
|
||||
Defaults to false. */
|
||||
bool lowPassFilter;
|
||||
|
||||
/** Height of the maximum ("white") value, in pixels, for the purpose of computing normals.
|
||||
A value of 255 means that a 255 x 255 bump image with a full black-to-white gradient
|
||||
will produce a 45-degree ramp (this also results in "cubic" voxels).
|
||||
A negative value means to set zExtentPixels to -zExtentPixels * max(width, height).
|
||||
The default is -0.02.
|
||||
*/
|
||||
float zExtentPixels;
|
||||
|
||||
/** After computing normals, scale the height by |N.z|, a trick that reduces texture swim in steep areas for parallax offset
|
||||
mapping. Defaults to false.*/
|
||||
bool scaleZByNz;
|
||||
|
||||
BumpMapPreprocess() : lowPassFilter(false), zExtentPixels(-0.02f), scaleZByNz(false) {}
|
||||
|
||||
BumpMapPreprocess(const Any& any);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
bool operator==(const BumpMapPreprocess& other) const {
|
||||
return
|
||||
(lowPassFilter == other.lowPassFilter) &&
|
||||
(zExtentPixels == other.zExtentPixels) &&
|
||||
(scaleZByNz == other.scaleZByNz);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
90
dep/g3dlite/include/G3D/Capsule.h
Normal file
90
dep/g3dlite/include/G3D/Capsule.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
@file Capsule.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2005-08-20
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CAPSULE_H
|
||||
#define G3D_CAPSULE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Line;
|
||||
class AABox;
|
||||
/**
|
||||
A shape formed by extruding a sphere along a line segment.
|
||||
*/
|
||||
class Capsule {
|
||||
private:
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
|
||||
float _radius;
|
||||
public:
|
||||
|
||||
|
||||
/** Uninitialized */
|
||||
Capsule();
|
||||
Capsule(class BinaryInput& b);
|
||||
Capsule(const Vector3& _p1, const Vector3& _p2, float _r);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** The line down the center of the capsule */
|
||||
Line axis() const;
|
||||
|
||||
inline float radius() const {
|
||||
return _radius;
|
||||
}
|
||||
|
||||
/** Argument may be 0 or 1 */
|
||||
inline Vector3 point(int i) const {
|
||||
debugAssert(i == 0 || i == 1);
|
||||
return (i == 0) ? p1 : p2;
|
||||
}
|
||||
|
||||
/** Distance between the sphere centers. The total extent of the cylinder is
|
||||
2r + h. */
|
||||
inline float height() const {
|
||||
return (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
inline Vector3 center() const {
|
||||
return (p1 + p2) / 2.0;
|
||||
}
|
||||
|
||||
/** Get a reference frame in which the center of mass is the origin and Y is the axis of the capsule.*/
|
||||
void getReferenceFrame(class CoordinateFrame& cframe) const;
|
||||
|
||||
/**
|
||||
Returns true if the point is inside the capsule or on its surface.
|
||||
*/
|
||||
bool contains(const Vector3& p) const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
float area() const;
|
||||
|
||||
/** Get axis aligned bounding box */
|
||||
void getBounds(AABox& out) const;
|
||||
|
||||
/** Random world space point with outward facing normal. */
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
|
||||
|
||||
/** Point selected uniformly at random over the volume. */
|
||||
Vector3 randomInteriorPoint() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
1205
dep/g3dlite/include/G3D/CollisionDetection.h
Normal file
1205
dep/g3dlite/include/G3D/CollisionDetection.h
Normal file
File diff suppressed because it is too large
Load Diff
171
dep/g3dlite/include/G3D/Color1.h
Normal file
171
dep/g3dlite/include/G3D/Color1.h
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
\file G3D/Color1.h
|
||||
|
||||
Monochrome Color class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
\created 2007-01-31
|
||||
\edited 2011-08-20
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color1_h
|
||||
#define G3D_Color1_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/unorm8.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Monochrome color.
|
||||
*/
|
||||
class Color1 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color1&) const;
|
||||
bool operator>(const Color1&) const;
|
||||
bool operator<=(const Color1&) const;
|
||||
bool operator>=(const Color1&) const;
|
||||
|
||||
public:
|
||||
float value;
|
||||
|
||||
/**
|
||||
Initializes to 0
|
||||
*/
|
||||
inline Color1() : value(0) {}
|
||||
|
||||
Color1(class BinaryInput& bi);
|
||||
|
||||
inline explicit Color1(float v) : value(v) {
|
||||
}
|
||||
|
||||
inline explicit Color1(unorm8 v) : value(v) {
|
||||
}
|
||||
|
||||
inline bool isZero() const {
|
||||
return value == 0.0f;
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return value == 1.0f;
|
||||
}
|
||||
|
||||
static const Color1& one();
|
||||
|
||||
static const Color1& zero();
|
||||
|
||||
/** Returns the value three times */
|
||||
class Color3 rgb() const;
|
||||
|
||||
explicit Color1(const class Color1unorm8& other);
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
Color1 operator+ (const Color1& other) const {
|
||||
return Color1(value + other.value);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
Color1 operator+ (const float other) const {
|
||||
return Color1(value + other);
|
||||
}
|
||||
|
||||
Color1& operator+= (const Color1 other) {
|
||||
value += other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1& operator-= (const Color1 other) {
|
||||
value -= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1 operator- (const Color1& other) const {
|
||||
return Color1(value - other.value);
|
||||
}
|
||||
|
||||
/** \deprecated */
|
||||
Color1 operator- (const float other) const {
|
||||
return Color1(value - other);
|
||||
}
|
||||
|
||||
Color1 operator- () const {
|
||||
return Color1(-value);
|
||||
}
|
||||
|
||||
Color1 operator* (const Color1& other) const {
|
||||
return Color1(value * other.value);
|
||||
}
|
||||
|
||||
Color1& operator*=(const Color1 other) {
|
||||
value *= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1& operator*=(const float other) {
|
||||
value *= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1& operator/=(const float other) {
|
||||
value /= other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1& operator/=(const Color1 other) {
|
||||
value /= other.value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color1 operator* (const float other) const {
|
||||
return Color1(value * other);
|
||||
}
|
||||
|
||||
Color1 operator/ (const Color1& other) const {
|
||||
return Color1(value / other.value);
|
||||
}
|
||||
|
||||
Color1 operator/ (const float other) const {
|
||||
return Color1(value / other);
|
||||
}
|
||||
|
||||
inline Color1 max(const Color1& other) const {
|
||||
return Color1(G3D::max(value, other.value));
|
||||
}
|
||||
|
||||
inline Color1 min(const Color1& other) const {
|
||||
return Color1(G3D::min(value, other.value));
|
||||
}
|
||||
|
||||
inline Color1 lerp(const Color1& other, float a) const {
|
||||
return Color1(value + (other.value - value) * a);
|
||||
|
||||
}
|
||||
|
||||
inline size_t hashCode() const {
|
||||
return (size_t)(value * 0xFFFFFF);
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Color1> {
|
||||
static size_t hashCode(const G3D::Color1& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
inline G3D::Color1 operator*(float f, G3D::Color1 c) {
|
||||
return c * f;
|
||||
}
|
||||
|
||||
#endif
|
||||
91
dep/g3dlite/include/G3D/Color1uint8.h
Normal file
91
dep/g3dlite/include/G3D/Color1uint8.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
@file Color1uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, graphics3d.com
|
||||
|
||||
@created 2007-01-30
|
||||
@edited 2007-01-30
|
||||
|
||||
Copyright 2000-2007, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_COLOR1UINT8_H
|
||||
#define G3D_COLOR1UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color1 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
|
||||
<B>Note</B>:
|
||||
Conversion of a float32 to uint8 is accomplished by min(iFloor(f * 256)) and
|
||||
back to float32 by u / 255.0f. This gives equal size intervals.
|
||||
Consider a number line from 0 to 1 and a corresponding one from 0 to 255. If we use iRound(x * 255), then the mapping for three critical intervals are:
|
||||
|
||||
<pre>
|
||||
let s = 0.5/255
|
||||
float int size
|
||||
[0, s) -> 0 s
|
||||
[s, s * 3) -> 1 2*s
|
||||
(1 - s, 1] -> 255 s
|
||||
</pre>
|
||||
|
||||
If we use max(floor(x * 256), 255), then we get:
|
||||
|
||||
<pre>
|
||||
let s = 1/256
|
||||
float int size
|
||||
[0, s) -> 0 s
|
||||
[s, 2 * s) -> 1 s
|
||||
(1 - s, 1] -> 255 s
|
||||
</PRE>
|
||||
and the intervals are all the same size, thus giving equal precision to all values.
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
class Color1uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color1uint8&) const;
|
||||
bool operator>(const Color1uint8&) const;
|
||||
bool operator<=(const Color1uint8&) const;
|
||||
bool operator>=(const Color1uint8&) const;
|
||||
|
||||
public:
|
||||
|
||||
uint8 value;
|
||||
|
||||
Color1uint8() : value(0) {}
|
||||
|
||||
explicit Color1uint8(const uint8 _v) : value(_v) {}
|
||||
|
||||
Color1uint8(const class Color1& c);
|
||||
|
||||
Color1uint8(class BinaryInput& bi);
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
inline bool operator==(const Color1uint8& other) const {
|
||||
return value == other.value;
|
||||
}
|
||||
|
||||
inline bool operator!=(const Color1uint8& other) const {
|
||||
return value != other.value;
|
||||
}
|
||||
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
}
|
||||
#endif
|
||||
483
dep/g3dlite/include/G3D/Color3.h
Normal file
483
dep/g3dlite/include/G3D/Color3.h
Normal file
@@ -0,0 +1,483 @@
|
||||
/**
|
||||
\file Color3.h
|
||||
|
||||
Color class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
\cite Portions based on Dave Eberly's Magic Software Library
|
||||
at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
|
||||
|
||||
\created 2001-06-02
|
||||
\edited 2013-03-29
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color3_h
|
||||
#define G3D_Color3_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Color3 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color3&) const;
|
||||
bool operator>(const Color3&) const;
|
||||
bool operator<=(const Color3&) const;
|
||||
bool operator>=(const Color3&) const;
|
||||
|
||||
public:
|
||||
/**
|
||||
\brief Initializes to all zero.
|
||||
*/
|
||||
Color3() : r(0), g(0), b(0) {}
|
||||
|
||||
bool nonZero() const {
|
||||
return (r != 0) || (g != 0) || (b != 0);
|
||||
}
|
||||
|
||||
/** \param any Must be in one of the following forms:
|
||||
- Color3(#, #, #)
|
||||
- Color3(#)
|
||||
- Color3::fromARGB(#)
|
||||
- Color3::fromASRGB(#)
|
||||
- Color3{r = #, g = #, b = #)
|
||||
- Color3::one()
|
||||
- Color3::zero()
|
||||
|
||||
In the current implementation, G3D::Power3, G3D::Radiance3,
|
||||
and G3D::Irradiance3 are typedefs for Color3, so Color3
|
||||
accepts "Power3" and "Radiance3" as a prefixes as well, e.g.,
|
||||
Power3(1,0,0).
|
||||
*/
|
||||
explicit Color3(const Any& any);
|
||||
|
||||
Color3& operator=(const Any& a);
|
||||
|
||||
/** Converts the Color3 to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
explicit Color3(class BinaryInput& bi);
|
||||
|
||||
Color3(float r, float g, float b);
|
||||
|
||||
/** \brief Initializes all channels to \a v */
|
||||
explicit Color3(float v) : r(v), g(v), b(v) {}
|
||||
|
||||
explicit Color3(const class Vector3& v);
|
||||
|
||||
explicit Color3(const float value[3]);
|
||||
|
||||
/** Returns this color */
|
||||
const Color3& rgb() const {
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize from another color.
|
||||
*/
|
||||
Color3 (const Color3& other);
|
||||
|
||||
Color3 (const class Color3unorm8& other);
|
||||
|
||||
inline bool isZero() const {
|
||||
return (r == 0.0f) && (g == 0.0f) && (b == 0.0f);
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return (r == 1.0f) && (g == 1.0f) && (b == 1.0f);
|
||||
}
|
||||
|
||||
bool isFinite() const;
|
||||
|
||||
/**
|
||||
Initialize from an HTML-style color (e.g. 0xFF0000 == RED)
|
||||
*/
|
||||
static Color3 fromARGB(uint32);
|
||||
|
||||
/**
|
||||
Initialize from an HTML-style color (e.g. 0xFF0000 == RED) by converting from sRGB to RGB.
|
||||
|
||||
*/
|
||||
static Color3 fromASRGB(uint32);
|
||||
|
||||
/** Returns one of the color wheel colors (e.g. RED, GREEN, CYAN).
|
||||
Does not include white, black, or gray. */
|
||||
static const Color3& wheelRandom();
|
||||
|
||||
/** Generate colors according to the ANSI color set, mod 16.
|
||||
\sa pastelMap */
|
||||
static Color3 ansiMap(uint32 i);
|
||||
|
||||
/**
|
||||
Generate colors using a hash such that adjacent values
|
||||
are unlikely to have similar colors.
|
||||
|
||||
Useful for rendering with
|
||||
stable but arbitrary colors, e.g., when debugging a mesh
|
||||
algorithm.
|
||||
|
||||
\sa ansiMap
|
||||
*/
|
||||
static Color3 pastelMap(uint32 i);
|
||||
|
||||
/**
|
||||
* Channel value.
|
||||
*/
|
||||
float r, g, b;
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color3 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);
|
||||
|
||||
// assignment and comparison
|
||||
Color3& operator= (const Color3& rkVector);
|
||||
bool operator== (const Color3& rkVector) const;
|
||||
bool operator!= (const Color3& rkVector) const;
|
||||
size_t hashCode() const;
|
||||
|
||||
// arithmetic operations
|
||||
Color3 operator+ (const Color3& rkVector) const;
|
||||
Color3 operator- (const Color3& rkVector) const;
|
||||
inline Color3 operator* (float s) const {
|
||||
return Color3(r * s, g * s, b * s);
|
||||
}
|
||||
inline Color3 operator/ (const Color3& rkVector) const {
|
||||
return Color3(r / rkVector.r, g / rkVector.g, b / rkVector.b);
|
||||
}
|
||||
|
||||
Color3 operator* (const Color3& rkVector) const;
|
||||
inline Color3 operator/ (float fScalar) const {
|
||||
return (*this) * (1.0f / fScalar);
|
||||
}
|
||||
|
||||
Color3 operator- () const;
|
||||
|
||||
// arithmetic updates
|
||||
Color3& operator+= (const Color3& rkVector);
|
||||
Color3& operator-= (const Color3& rkVector);
|
||||
Color3& operator*= (const Color3& rkVector);
|
||||
Color3& operator*= (float fScalar);
|
||||
Color3& operator/= (float fScalar);
|
||||
|
||||
bool fuzzyEq(const Color3& other) const;
|
||||
bool fuzzyNe(const Color3& other) const;
|
||||
|
||||
// vector operations
|
||||
float length () const;
|
||||
Color3 direction() const;
|
||||
float squaredLength () const;
|
||||
float dot (const Color3& rkVector) const;
|
||||
float unitize (float fTolerance = 1e-06f);
|
||||
Color3 cross (const Color3& rkVector) const;
|
||||
Color3 unitCross (const Color3& rkVector) const;
|
||||
|
||||
inline Color3 pow(const Color3& other) const {
|
||||
return Color3(::pow(r, other.r), ::pow(g, other.g), ::pow(b, other.b));
|
||||
}
|
||||
|
||||
inline Color3 pow(float other) const {
|
||||
return Color3(::pow(r, other), ::pow(g, other), ::pow(b, other));
|
||||
}
|
||||
|
||||
inline Color3 max(const Color3& other) const {
|
||||
return Color3(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b));
|
||||
}
|
||||
|
||||
inline Color3 min(const Color3& other) const {
|
||||
return Color3(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b));
|
||||
}
|
||||
|
||||
/** Smallest element */
|
||||
inline float min() const {
|
||||
return G3D::min(G3D::min(r, g), b);
|
||||
}
|
||||
|
||||
/** Largest element */
|
||||
inline float max() const {
|
||||
return G3D::max(G3D::max(r, g), b);
|
||||
}
|
||||
|
||||
inline Color3 lerp(const Color3& other, float a) const {
|
||||
return (*this) + (other - *this) * a;
|
||||
|
||||
}
|
||||
|
||||
inline float sum() const {
|
||||
return r + g + b;
|
||||
}
|
||||
|
||||
inline float average() const {
|
||||
return sum() / 3.0f;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Converts from HSV to RGB , note: toHSV(fromHSV(_hsv)) may not be _hsv, if it is at a grey point or black point.
|
||||
* The components of _hsv should lie in the unit interval.
|
||||
* @cite Alvy Ray Smith SIGGRAPH 1978 "Color Gamut Transform Pairs"
|
||||
**/
|
||||
static Color3 fromHSV(const Vector3& _hsv);
|
||||
static Vector3 toHSV(const Color3& _rgb);
|
||||
|
||||
/** Duplicates the matlab jet colormap maps [0,1] --> (r,g,b) where blue is close to 0 and red is close to 1. */
|
||||
static Color3 jetColorMap(const float& val);
|
||||
|
||||
/** Returns colors with maximum saturation and value @param hue [0, 1]*/
|
||||
static Color3 rainbowColorMap(float hue);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** Random unit vector */
|
||||
static Color3 random();
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Color3& red();
|
||||
static const Color3& green();
|
||||
static const Color3& blue();
|
||||
static const Color3& purple();
|
||||
static const Color3& cyan();
|
||||
static const Color3& yellow();
|
||||
static const Color3& brown();
|
||||
static const Color3& orange();
|
||||
static const Color3& black();
|
||||
static const Color3& gray();
|
||||
static const Color3& white();
|
||||
|
||||
static const Color3& zero();
|
||||
static const Color3& one();
|
||||
|
||||
inline Color3 bgr() const {
|
||||
return Color3(b, g, r);
|
||||
}
|
||||
};
|
||||
|
||||
inline G3D::Color3 operator* (float s, const G3D::Color3& c) {
|
||||
return c * s;
|
||||
}
|
||||
|
||||
inline G3D::Color3 operator* (G3D::Color1& s, const G3D::Color3& c) {
|
||||
return c * s.value;
|
||||
}
|
||||
|
||||
inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) {
|
||||
return c * s.value;
|
||||
}
|
||||
|
||||
inline G3D::Color3 operator/ (float s, const G3D::Color3& c) {
|
||||
return c * (1.0f/s);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color3::Color3(float fX, float fY, float fZ) {
|
||||
r = fX;
|
||||
g = fY;
|
||||
b = fZ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3::Color3(const float afCoordinate[3]) {
|
||||
r = afCoordinate[0];
|
||||
g = afCoordinate[1];
|
||||
b = afCoordinate[2];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3::Color3 (const Color3& rkVector) {
|
||||
r = rkVector.r;
|
||||
g = rkVector.g;
|
||||
b = rkVector.b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float& Color3::operator[] (int i) {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline const float& Color3::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color3::fuzzyEq(const Color3& other) const {
|
||||
return G3D::fuzzyEq((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color3::fuzzyNe(const Color3& other) const {
|
||||
return G3D::fuzzyNe((*this - other).squaredLength(), 0);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator= (const Color3& rkVector) {
|
||||
r = rkVector.r;
|
||||
g = rkVector.g;
|
||||
b = rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Color3::operator== (const Color3& rkVector) const {
|
||||
return ( r == rkVector.r && g == rkVector.g && b == rkVector.b );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool Color3::operator!= (const Color3& rkVector) const {
|
||||
return ( r != rkVector.r || g != rkVector.g || b != rkVector.b );
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator+ (const Color3& rkVector) const {
|
||||
return Color3(r + rkVector.r, g + rkVector.g, b + rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator- (const Color3& rkVector) const {
|
||||
return Color3(r -rkVector.r, g - rkVector.g, b - rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator* (const Color3& rkVector) const {
|
||||
return Color3(r * rkVector.r, g * rkVector.g, b * rkVector.b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::operator- () const {
|
||||
return Color3( -r, -g, -b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator+= (const Color3& rkVector) {
|
||||
r += rkVector.r;
|
||||
g += rkVector.g;
|
||||
b += rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator-= (const Color3& rkVector) {
|
||||
r -= rkVector.r;
|
||||
g -= rkVector.g;
|
||||
b -= rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator*= (float fScalar) {
|
||||
r *= fScalar;
|
||||
g *= fScalar;
|
||||
b *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3& Color3::operator*= (const Color3& rkVector) {
|
||||
r *= rkVector.r;
|
||||
g *= rkVector.g;
|
||||
b *= rkVector.b;
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::squaredLength () const {
|
||||
return r*r + g*g + b*b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::length () const {
|
||||
return sqrtf(r*r + g*g + b*b);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::direction () const {
|
||||
float lenSquared = r * r + g * g + b * b;
|
||||
|
||||
if (lenSquared != 1.0f) {
|
||||
return *this / sqrtf(lenSquared);
|
||||
} else {
|
||||
return *this;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline float Color3::dot (const Color3& rkVector) const {
|
||||
return r*rkVector.r + g*rkVector.g + b*rkVector.b;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::cross (const Color3& rkVector) const {
|
||||
return Color3(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
|
||||
r*rkVector.g - g*rkVector.r);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color3 Color3::unitCross (const Color3& rkVector) const {
|
||||
Color3 kCross(g*rkVector.b - b*rkVector.g, b*rkVector.r - r*rkVector.b,
|
||||
r*rkVector.g - g*rkVector.r);
|
||||
return kCross.direction();
|
||||
}
|
||||
|
||||
|
||||
/** Radiance * measure(Solid Angle) between two points, measured at the receiver orthogonal to the axis between them; W/m^2 */
|
||||
typedef Color3 Biradiance3;
|
||||
|
||||
/** Power per (measure(SolidAngle) * measure(Area)); W / (m^2 sr) */
|
||||
typedef Color3 Radiance3;
|
||||
|
||||
/** Power per area; J / m^2 */
|
||||
typedef Color3 Radiosity3;
|
||||
|
||||
/** Force * distance; J */
|
||||
typedef Color3 Energy3;
|
||||
|
||||
/** Incident power per area; W/m^2*/
|
||||
typedef Color3 Irradiance3;
|
||||
|
||||
/** Energy per time; W*/
|
||||
typedef Color3 Power3;
|
||||
|
||||
#if 0 // Disabled to avoid taking these useful names from the namespace
|
||||
typedef float Power;
|
||||
typedef float Biradiance;
|
||||
typedef float Radiance;
|
||||
typedef float Radiosity;
|
||||
typedef float Energy;
|
||||
typedef float Irradiance;
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
|
||||
template <> struct HashTrait<G3D::Color3> {
|
||||
static size_t hashCode(const G3D::Color3& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
125
dep/g3dlite/include/G3D/Color3uint8.h
Normal file
125
dep/g3dlite/include/G3D/Color3uint8.h
Normal file
@@ -0,0 +1,125 @@
|
||||
/**
|
||||
@file Color3uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-04-07
|
||||
@edited 2010-03-24
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color3uint8_h
|
||||
#define G3D_Color3uint8_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color3 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays. Used by
|
||||
G3D::GImage as the underlying format.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color3(1,1,1) == Color3uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
*/
|
||||
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
|
||||
class Color3uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color3uint8&) const;
|
||||
bool operator>(const Color3uint8&) const;
|
||||
bool operator<=(const Color3uint8&) const;
|
||||
bool operator>=(const Color3uint8&) const;
|
||||
|
||||
public:
|
||||
uint8 r;
|
||||
uint8 g;
|
||||
uint8 b;
|
||||
|
||||
Color3uint8() : r(0), g(0), b(0) {}
|
||||
|
||||
Color3uint8(const uint8 _r, const uint8 _g, const uint8 _b) : r(_r), g(_g), b(_b) {}
|
||||
|
||||
Color3uint8(const class Color3& c);
|
||||
|
||||
Color3uint8(class BinaryInput& bi);
|
||||
|
||||
static Color3uint8 fromARGB(uint32 i) {
|
||||
Color3uint8 c;
|
||||
c.r = (i >> 16) & 0xFF;
|
||||
c.g = (i >> 8) & 0xFF;
|
||||
c.b = i & 0xFF;
|
||||
return c;
|
||||
}
|
||||
|
||||
Color3uint8 bgr() const {
|
||||
return Color3uint8(b, g, r);
|
||||
}
|
||||
|
||||
Color3uint8 max(const Color3uint8 x) const {
|
||||
return Color3uint8(G3D::max(r, x.r), G3D::max(g, x.g), G3D::max(b, x.b));
|
||||
}
|
||||
|
||||
Color3uint8 min(const Color3uint8 x) const {
|
||||
return Color3uint8(G3D::min(r, x.r), G3D::min(g, x.g), G3D::min(b, x.b));
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the color packed into a uint32
|
||||
(the upper byte is 0xFF)
|
||||
*/
|
||||
uint32 asUInt32() const {
|
||||
return (0xFF << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color3 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(uint8) memory block
|
||||
uint8& operator[] (int i) const {
|
||||
debugAssert((unsigned int)i < 3);
|
||||
return ((uint8*)this)[i];
|
||||
}
|
||||
|
||||
operator uint8* () {
|
||||
return (G3D::uint8*)this;
|
||||
}
|
||||
|
||||
operator const uint8* () const {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
bool operator==(const Color3uint8 other) const {
|
||||
return (other.r == r) && (other.g == g) && (other.b == b);
|
||||
}
|
||||
|
||||
bool operator!=(const Color3uint8 other) const {
|
||||
return ! (*this == other);
|
||||
}
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
341
dep/g3dlite/include/G3D/Color4.h
Normal file
341
dep/g3dlite/include/G3D/Color4.h
Normal file
@@ -0,0 +1,341 @@
|
||||
/**
|
||||
@file Color4.h
|
||||
|
||||
Color class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@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 2002-06-25
|
||||
@edited 2009-11-15
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Color4_h
|
||||
#define G3D_Color4_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Do not subclass-- this implementation makes assumptions about the
|
||||
memory layout.
|
||||
*/
|
||||
class Color4 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color4&) const;
|
||||
bool operator>(const Color4&) const;
|
||||
bool operator<=(const Color4&) const;
|
||||
bool operator>=(const Color4&) const;
|
||||
|
||||
public:
|
||||
|
||||
/** \param any Must be in one of the following forms:
|
||||
- Color4(#, #, #, #)
|
||||
- Color4::fromARGB(#)
|
||||
- Color4{r = #, g = #, b = #, a = #)
|
||||
*/
|
||||
Color4(const Any& any);
|
||||
|
||||
/** Converts the Color4 to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
/**
|
||||
Initializes to all zero
|
||||
*/
|
||||
Color4() : r(0), g(0), b(0), a(0) {}
|
||||
|
||||
Color4(const Color3& c3, float a = 1.0);
|
||||
|
||||
Color4(const class Color4unorm8& c);
|
||||
|
||||
Color4(class BinaryInput& bi);
|
||||
|
||||
Color4(const class Vector4& v);
|
||||
|
||||
Color4(float r, float g, float b, float a = 1.0);
|
||||
|
||||
static const Color4& one();
|
||||
|
||||
Color4(float value[4]);
|
||||
|
||||
/**
|
||||
* Initialize from another color.
|
||||
*/
|
||||
Color4(const Color4& other);
|
||||
|
||||
|
||||
inline bool isZero() const {
|
||||
return (r == 0.0f) && (g == 0.0f) && (b == 0.0f) && (a == 0.0f);
|
||||
}
|
||||
|
||||
inline bool isOne() const {
|
||||
return (r == 1.0f) && (g == 1.0f) && (b == 1.0f) && (a == 1.0f);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
/**
|
||||
Initialize from an HTML-style color (e.g. 0xFFFF0000 == RED)
|
||||
*/
|
||||
static Color4 fromARGB(uint32);
|
||||
|
||||
/**
|
||||
* Channel values.
|
||||
*/
|
||||
float r, g, b, a;
|
||||
|
||||
inline Color3 rgb() const {
|
||||
return Color3(r, g, b);
|
||||
}
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b, v[3] = V.a
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color4 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(float) memory block
|
||||
float& operator[] (int i) const;
|
||||
|
||||
// assignment and comparison
|
||||
Color4& operator= (const Color4& rkVector);
|
||||
bool operator== (const Color4& rkVector) const;
|
||||
bool operator!= (const Color4& rkVector) const;
|
||||
size_t hashCode() const;
|
||||
|
||||
// arithmetic operations
|
||||
Color4 operator+ (const Color4& rkVector) const;
|
||||
Color4 operator- (const Color4& rkVector) const;
|
||||
Color4 operator* (float fScalar) const;
|
||||
Color4 operator* (const Color4& k) const {
|
||||
return Color4(r*k.r, g*k.g, b*k.b, a * k.a);
|
||||
}
|
||||
|
||||
Color4& operator*= (const Color4& c) {
|
||||
r *= c.r;
|
||||
g *= c.g;
|
||||
b *= c.b;
|
||||
a *= c.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Color4 operator/ (float fScalar) const;
|
||||
Color4 operator- () const;
|
||||
friend Color4 operator* (double fScalar, const Color4& rkVector);
|
||||
|
||||
// arithmetic updates
|
||||
Color4& operator+= (const Color4& rkVector);
|
||||
Color4& operator-= (const Color4& rkVector);
|
||||
Color4& operator*= (float fScalar);
|
||||
Color4& operator/= (float fScalar);
|
||||
|
||||
bool fuzzyEq(const Color4& other) const;
|
||||
bool fuzzyNe(const Color4& other) const;
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
inline Color4 max(const Color4& other) const {
|
||||
return Color4(G3D::max(r, other.r), G3D::max(g, other.g), G3D::max(b, other.b), G3D::max(a, other.a));
|
||||
}
|
||||
|
||||
inline Color4 min(const Color4& other) const {
|
||||
return Color4(G3D::min(r, other.r), G3D::min(g, other.g), G3D::min(b, other.b), G3D::min(a, other.a));
|
||||
}
|
||||
|
||||
/** r + g + b + a */
|
||||
inline float sum() const {
|
||||
return r + g + b + a;
|
||||
}
|
||||
|
||||
inline Color4 lerp(const Color4& other, float a) const {
|
||||
return (*this) + (other - *this) * a;
|
||||
|
||||
}
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Color4& zero();
|
||||
static const Color4& clear();
|
||||
|
||||
static const Color4& inf();
|
||||
static const Color4& nan();
|
||||
|
||||
inline bool isFinite() const {
|
||||
return G3D::isFinite(r) && G3D::isFinite(g) && G3D::isFinite(b) && G3D::isFinite(a);
|
||||
}
|
||||
|
||||
inline Color3 bgr() const {
|
||||
return Color3(b, g, r);
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Extends the c3 with alpha = 1.0
|
||||
*/
|
||||
Color4 operator*(const Color3& c3, const Color4& c4);
|
||||
|
||||
|
||||
inline Color4 operator*(const Color3& c3, const Color4& c4) {
|
||||
return Color4(c3.r * c4.r, c3.g * c4.g, c3.b * c4.b, c4.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
|
||||
inline Color4::Color4(const Color3& c3, float a) {
|
||||
r = c3.r;
|
||||
g = c3.g;
|
||||
b = c3.b;
|
||||
this->a = a;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4(
|
||||
float r,
|
||||
float g,
|
||||
float b,
|
||||
float a) :
|
||||
r(r), g(g), b(b), a(a) {
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4::Color4 (float afCoordinate[4]) {
|
||||
r = afCoordinate[0];
|
||||
g = afCoordinate[1];
|
||||
b = afCoordinate[2];
|
||||
a = afCoordinate[3];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4::Color4(
|
||||
const Color4& other) {
|
||||
|
||||
r = other.r;
|
||||
g = other.g;
|
||||
b = other.b;
|
||||
a = other.a;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline float& Color4::operator[] (int i) const {
|
||||
return ((float*)this)[i];
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::fuzzyEq(const Color4& other) const {
|
||||
Color4 dif = (*this - other);
|
||||
return G3D::fuzzyEq(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::fuzzyNe(const Color4& other) const {
|
||||
Color4 dif = (*this - other);
|
||||
return G3D::fuzzyNe(dif.r * dif.r + dif.g * dif.g + dif.b * dif.b + dif.a * dif.a, 0);
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4& Color4::operator= (const Color4& other) {
|
||||
r = other.r;
|
||||
g = other.g;
|
||||
b = other.b;
|
||||
a = other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::operator== (const Color4& other) const {
|
||||
return ( r == other.r && g == other.g && b == other.b && a == other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Color4::operator!= (const Color4& other) const {
|
||||
return ( r != other.r || g != other.g || b != other.b || a != other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4 Color4::operator+ (const Color4& other) const {
|
||||
return Color4(r + other.r, g + other.g, b + other.b, a + other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline Color4 Color4::operator- (const Color4& other) const {
|
||||
return Color4(r - other.r, g - other.g, b - other.b, a - other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 Color4::operator* (float fScalar) const {
|
||||
return Color4(fScalar * r, fScalar * g, fScalar * b, fScalar * a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 Color4::operator- () const {
|
||||
return Color4(-r, -g, -b, -a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4 operator* (float fScalar, const Color4& other) {
|
||||
return Color4(fScalar * other.r, fScalar * other.g,
|
||||
fScalar * other.b, fScalar * other.a);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator+= (const Color4& other) {
|
||||
r += other.r;
|
||||
g += other.g;
|
||||
b += other.b;
|
||||
a += other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator-= (const Color4& other) {
|
||||
r -= other.r;
|
||||
g -= other.g;
|
||||
b -= other.b;
|
||||
a -= other.a;
|
||||
return *this;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline Color4& Color4::operator*= (float fScalar) {
|
||||
r *= fScalar;
|
||||
g *= fScalar;
|
||||
b *= fScalar;
|
||||
a *= fScalar;
|
||||
return *this;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Color4> {
|
||||
static size_t hashCode(const G3D::Color4& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
123
dep/g3dlite/include/G3D/Color4uint8.h
Normal file
123
dep/g3dlite/include/G3D/Color4uint8.h
Normal file
@@ -0,0 +1,123 @@
|
||||
/**
|
||||
@file Color4uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-04-07
|
||||
@edited 2010-03-24
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef COLOR4UINT8_H
|
||||
#define COLOR4UINT8_H
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Represents a Color4 as a packed integer. Convenient
|
||||
for creating unsigned int vertex arrays. Used by
|
||||
G3D::GImage as the underlying format.
|
||||
|
||||
<B>WARNING</B>: Integer color formats are different than
|
||||
integer vertex formats. The color channels are automatically
|
||||
scaled by 255 (because OpenGL automatically scales integer
|
||||
colors back by this factor). So Color4(1,1,1) == Color4uint8(255,255,255)
|
||||
but Vector3(1,1,1) == Vector3int16(1,1,1).
|
||||
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(1)
|
||||
class Color4uint8 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Color4uint8&) const;
|
||||
bool operator>(const Color4uint8&) const;
|
||||
bool operator<=(const Color4uint8&) const;
|
||||
bool operator>=(const Color4uint8&) const;
|
||||
|
||||
public:
|
||||
uint8 r;
|
||||
uint8 g;
|
||||
uint8 b;
|
||||
uint8 a;
|
||||
|
||||
Color4uint8() : r(0), g(0), b(0), a(0) {}
|
||||
|
||||
Color4uint8(const class Color4& c);
|
||||
|
||||
Color4uint8 max(const Color4uint8 x) const {
|
||||
return Color4uint8(G3D::max(r, x.r), G3D::max(g, x.g), G3D::max(b, x.b), G3D::max(a, x.a));
|
||||
}
|
||||
|
||||
Color4uint8 min(const Color4uint8 x) const {
|
||||
return Color4uint8(G3D::min(r, x.r), G3D::min(g, x.g), G3D::min(b, x.b), G3D::min(a, x.a));
|
||||
}
|
||||
|
||||
Color4uint8(const uint8 _r, const uint8 _g, const uint8 _b, const uint8 _a) : r(_r), g(_g), b(_b), a(_a) {}
|
||||
|
||||
Color4uint8(const Color3uint8& c, const uint8 _a) : r(c.r), g(c.g), b(c.b), a(_a) {}
|
||||
|
||||
Color4uint8(class BinaryInput& bi);
|
||||
|
||||
inline static Color4uint8 fromARGB(uint32 i) {
|
||||
Color4uint8 c;
|
||||
c.a = (i >> 24) & 0xFF;
|
||||
c.r = (i >> 16) & 0xFF;
|
||||
c.g = (i >> 8) & 0xFF;
|
||||
c.b = i & 0xFF;
|
||||
return c;
|
||||
}
|
||||
|
||||
inline uint32 asUInt32() const {
|
||||
return ((uint32)a << 24) + ((uint32)r << 16) + ((uint32)g << 8) + b;
|
||||
}
|
||||
|
||||
// access vector V as V[0] = V.r, V[1] = V.g, V[2] = V.b
|
||||
//
|
||||
// WARNING. These member functions rely on
|
||||
// (1) Color4uint8 not having virtual functions
|
||||
// (2) the data packed in a 3*sizeof(uint8) memory block
|
||||
uint8& operator[] (int i) const {
|
||||
return ((uint8*)this)[i];
|
||||
}
|
||||
|
||||
operator uint8* () {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
operator const uint8* () const {
|
||||
return (uint8*)this;
|
||||
}
|
||||
|
||||
|
||||
inline Color3uint8 bgr() const {
|
||||
return Color3uint8(b, g, r);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
inline Color3uint8 rgb() const {
|
||||
return Color3uint8(r, g, b);
|
||||
}
|
||||
|
||||
bool operator==(const Color4uint8& other) const {
|
||||
return *reinterpret_cast<const uint32*>(this) == *reinterpret_cast<const uint32*>(&other);
|
||||
}
|
||||
|
||||
bool operator!=(const Color4uint8& other) const {
|
||||
return *reinterpret_cast<const uint32*>(this) != *reinterpret_cast<const uint32*>(&other);
|
||||
}
|
||||
|
||||
}
|
||||
G3D_END_PACKED_CLASS(1)
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
81
dep/g3dlite/include/G3D/Cone.h
Normal file
81
dep/g3dlite/include/G3D/Cone.h
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
@file Cone.h
|
||||
|
||||
Cone class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@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-02-23
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CONE_H
|
||||
#define G3D_CONE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An infinite cone.
|
||||
*/
|
||||
class Cone {
|
||||
|
||||
private:
|
||||
Vector3 tip;
|
||||
Vector3 direction;
|
||||
|
||||
/** Angle from the center line to the edge. */
|
||||
float angle;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param angle Angle from the center line to the edge, in radians
|
||||
*/
|
||||
Cone(const Vector3& tip, const Vector3& direction, float angle);
|
||||
|
||||
/**
|
||||
Forms the smallest cone that contains the box. Undefined if
|
||||
the tip is inside or on the box.
|
||||
*/
|
||||
Cone(const Vector3& tip, const class Box& box);
|
||||
|
||||
virtual ~Cone() {}
|
||||
|
||||
/**
|
||||
Returns true if the cone touches, intersects, or contains b.
|
||||
|
||||
If c.intersects(s) and c.intersects(Sphere(s.center, s.radius * 2)
|
||||
then the sphere s is entirely within cone c.
|
||||
*/
|
||||
bool intersects(const class Sphere& s) const;
|
||||
|
||||
/**
|
||||
True if v is a point inside the cone.
|
||||
*/
|
||||
bool contains(const class Vector3& v) const;
|
||||
|
||||
|
||||
/** Returns the solid angle (in steradians) subtended by a cone with half-angle \a halfAngle */
|
||||
static float solidAngleFromHalfAngle(float halfAngle);
|
||||
static double solidAngleFromHalfAngle(double halfAngle);
|
||||
|
||||
/** Returns the half-angle (in radians) of a cone that subtends \a solidAngle (in steradians) */
|
||||
static float halfAngleFromSolidAngle(float solidAngle);
|
||||
static double halfAngleFromSolidAngle(double solidAngle);
|
||||
|
||||
|
||||
Vector3 randomDirectionInCone(Random& rng) const;
|
||||
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
180
dep/g3dlite/include/G3D/ConvexPolyhedron.h
Normal file
180
dep/g3dlite/include/G3D/ConvexPolyhedron.h
Normal file
@@ -0,0 +1,180 @@
|
||||
/**
|
||||
@file ConvexPolyhedron.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-11-11
|
||||
@edited 2006-04-10
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CONVEXPOLYHEDRON_H
|
||||
#define G3D_CONVEXPOLYHEDRON_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/Array.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class DirectedEdge {
|
||||
public:
|
||||
Vector3 start;
|
||||
Vector3 stop;
|
||||
};
|
||||
|
||||
class ConvexPolygon {
|
||||
private:
|
||||
|
||||
friend class ConvexPolyhedron;
|
||||
|
||||
Array<Vector3> _vertex;
|
||||
|
||||
public:
|
||||
|
||||
ConvexPolygon() {}
|
||||
ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3& v2);
|
||||
ConvexPolygon(const Array<Vector3>& __vertex);
|
||||
virtual ~ConvexPolygon() {}
|
||||
|
||||
/**
|
||||
Counter clockwise winding order.
|
||||
*/
|
||||
inline const Vector3& vertex(int i) const {
|
||||
return _vertex[i];
|
||||
}
|
||||
|
||||
inline void setVertex(int i, const Vector3& v) {
|
||||
_vertex[i] = v;
|
||||
}
|
||||
|
||||
/**
|
||||
Zero vertices indicates an empty polygon (zero area).
|
||||
*/
|
||||
inline int numVertices() const {
|
||||
return _vertex.size();
|
||||
}
|
||||
|
||||
inline void setNumVertices(int n) {
|
||||
_vertex.resize(n);
|
||||
}
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
Cuts the polygon at the plane. If the polygon is entirely above or below
|
||||
the plane, one of the returned polygons will be empty.
|
||||
|
||||
@param above The part of the polygon above (on the side the
|
||||
normal points to or in the plane) the plane
|
||||
@param below The part of the polygon below the plane.
|
||||
@param newEdge If a new edge was introduced, this is that edge (on the above portion; the below portion is the opposite winding.
|
||||
*/
|
||||
void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below, DirectedEdge& newEdge);
|
||||
void cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon &below);
|
||||
|
||||
/**
|
||||
When a cut plane grazes a vertex in the polygon, two near-identical vertices may be created.
|
||||
The closeness of these two points can cause a number of problems, such as ConvexPolygon::normal()
|
||||
returning an infinite vector. It should be noted, however, that not all applications are
|
||||
sensitive to near-identical vertices.
|
||||
|
||||
removeDuplicateVertices() detects and eliminates redundant vertices.
|
||||
*/
|
||||
void removeDuplicateVertices();
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
float getArea() const;
|
||||
|
||||
inline Vector3 normal() const {
|
||||
debugAssert(_vertex.length() >= 3);
|
||||
return (_vertex[1] - _vertex[0]).cross(_vertex[2] - _vertex[0]).direction();
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the same polygon with inverse winding.
|
||||
*/
|
||||
ConvexPolygon inverse() const;
|
||||
};
|
||||
|
||||
|
||||
|
||||
class ConvexPolyhedron {
|
||||
public:
|
||||
/**
|
||||
Zero faces indicates an empty polyhedron
|
||||
*/
|
||||
Array<ConvexPolygon> face;
|
||||
|
||||
ConvexPolyhedron() {}
|
||||
ConvexPolyhedron(const Array<ConvexPolygon>& _face);
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
O(n) in the number of edges
|
||||
*/
|
||||
float getVolume() const;
|
||||
|
||||
/**
|
||||
Cuts the polyhedron at the plane. If the polyhedron is entirely above or below
|
||||
the plane, one of the returned polyhedra will be empty.
|
||||
|
||||
@param above The part of the polyhedron above (on the side the
|
||||
normal points to or in the plane) the plane
|
||||
@param below The part of the polyhedron below the plane.
|
||||
*/
|
||||
void cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
*/
|
||||
class ConvexPolygon2D {
|
||||
private:
|
||||
|
||||
Array<Vector2> m_vertex;
|
||||
|
||||
public:
|
||||
|
||||
ConvexPolygon2D() {}
|
||||
|
||||
/**
|
||||
Points are counter-clockwise in a Y = down, X = right coordinate
|
||||
system.
|
||||
|
||||
@param reverse If true, the points are reversed (i.e. winding direction is changed)
|
||||
before the polygon is created.
|
||||
*/
|
||||
ConvexPolygon2D(const Array<Vector2>& pts, bool reverse = false);
|
||||
|
||||
inline int numVertices() const {
|
||||
return m_vertex.size();
|
||||
}
|
||||
|
||||
inline const Vector2& vertex(int index) const {
|
||||
debugAssert((index >= 0) && (index <= m_vertex.size()));
|
||||
return m_vertex[index];
|
||||
}
|
||||
|
||||
/** @param reverseWinding If true, the winding direction of the polygon is reversed for this test.*/
|
||||
bool contains(const Vector2& p, bool reverseWinding = false) const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
356
dep/g3dlite/include/G3D/CoordinateFrame.h
Normal file
356
dep/g3dlite/include/G3D/CoordinateFrame.h
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
\file G3D/CoordinateFrame.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-03-04
|
||||
\edited 2012-07-29
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_CFrame_h
|
||||
#define G3D_CFrame_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>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
class Frustum;
|
||||
|
||||
/**
|
||||
\brief 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.
|
||||
|
||||
\sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat
|
||||
*/
|
||||
class CoordinateFrame {
|
||||
public:
|
||||
|
||||
/** Takes object space points to world space. */
|
||||
Matrix3 rotation;
|
||||
|
||||
/** The origin of this coordinate frame in world space (or its parent's space, if nested). */
|
||||
Point3 translation;
|
||||
|
||||
/** \param any Must be in one of the following forms:
|
||||
- CFrame((matrix3 expr), (Point3 expr))
|
||||
- CFrame::fromXYZYPRDegrees(#, #, #, #, #, #)
|
||||
- CFrame { rotation = (Matrix3 expr), translation = (Point3 expr) }
|
||||
- Point3( ... )
|
||||
- Matrix3( ... )
|
||||
*/
|
||||
CoordinateFrame(const Any& any);
|
||||
|
||||
/** Converts the CFrame to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
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.
|
||||
*/
|
||||
CoordinateFrame();
|
||||
|
||||
CoordinateFrame(const Point3& _translation) :
|
||||
rotation(Matrix3::identity()), translation(_translation) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const Matrix3& rotation, const Point3& translation) :
|
||||
rotation(rotation), translation(translation) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const Matrix3& rotation) :
|
||||
rotation(rotation), translation(Point3::zero()) {
|
||||
}
|
||||
|
||||
CoordinateFrame(const class UprightFrame& f);
|
||||
|
||||
static CoordinateFrame fromXYZYPRRadians(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
|
||||
|
||||
std::string toXYZYPRDegreesString() const;
|
||||
|
||||
/** Construct a coordinate frame from translation = (x,y,z) and
|
||||
rotations (in that order) about Y, object space X, object space
|
||||
Z. Note that because object-space axes are used, these are not
|
||||
equivalent to Euler angles; they are known as Tait-Bryan
|
||||
rotations and are more convenient for intuitive positioning.*/
|
||||
static CoordinateFrame fromXYZYPRDegrees(float x, float y, float z, float yaw = 0.0f, float pitch = 0.0f, float roll = 0.0f);
|
||||
|
||||
CoordinateFrame(class BinaryInput& b);
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
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;
|
||||
|
||||
void getXYZYPRRadians(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
|
||||
void getXYZYPRDegrees(float& x, float& y, float& z, float& yaw, float& pitch, float& roll) const;
|
||||
|
||||
|
||||
/**
|
||||
Produces an XML serialization of this coordinate frame.
|
||||
@deprecated
|
||||
*/
|
||||
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.column(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 Point3 pointToWorldSpace(const Point3& v) const {
|
||||
return Point3
|
||||
(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. Assumes that the rotation matrix is orthonormal.
|
||||
*/
|
||||
inline Point3 pointToObjectSpace(const Point3& v) const {
|
||||
float p[3];
|
||||
p[0] = v[0] - translation[0];
|
||||
p[1] = v[1] - translation[1];
|
||||
p[2] = v[2] - translation[2];
|
||||
debugAssert(G3D::fuzzyEq(fabsf(rotation.determinant()), 1.0f));
|
||||
return Point3(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;
|
||||
|
||||
Frustum toWorldSpace(const Frustum& f) 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<Point3>& v, Array<Point3>& 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<Point3>& v, Array<Point3>& vout) const;
|
||||
|
||||
void normalToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void vectorToObjectSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
|
||||
|
||||
void toWorldSpace(const class AABox& b, class AABox& result) 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);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Transform this coordinate frame towards \a goal, but not past it, goverened by maximum
|
||||
rotation and translations. This is a useful alternative to \a lerp, especially if the
|
||||
goal is expected to change every transformation step so that constant start and end positions will
|
||||
not be available.
|
||||
|
||||
\param goal Step from this towards goal
|
||||
\param maxTranslation Meters
|
||||
\param maxRotation Radians
|
||||
|
||||
\sa lerp
|
||||
*/
|
||||
void moveTowards(const CoordinateFrame& goal, float maxTranslation, float maxRotation);
|
||||
|
||||
void lookAt(const Point3& target);
|
||||
|
||||
void lookAt
|
||||
(const Point3& target,
|
||||
Vector3 up);
|
||||
|
||||
/** The direction this camera is looking (its negative z axis)*/
|
||||
inline Vector3 lookVector() const {
|
||||
return -rotation.column(2);
|
||||
}
|
||||
|
||||
/** 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.column(1);
|
||||
}
|
||||
|
||||
inline Vector3 rightVector() const {
|
||||
return rotation.column(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.column(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Linearly interpolates between two coordinate frames, using
|
||||
Quat::slerp for the rotations.
|
||||
|
||||
\sa moveTowards
|
||||
*/
|
||||
CoordinateFrame lerp
|
||||
(const CoordinateFrame& other,
|
||||
float alpha) const;
|
||||
|
||||
};
|
||||
|
||||
typedef CoordinateFrame CFrame;
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
127
dep/g3dlite/include/G3D/Crypto.h
Normal file
127
dep/g3dlite/include/G3D/Crypto.h
Normal file
@@ -0,0 +1,127 @@
|
||||
/**
|
||||
\file G3D/Crypto.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
|
||||
\created 2006-03-29
|
||||
\edited 2011-06-21
|
||||
*/
|
||||
|
||||
#ifndef G3D_Crypto_h
|
||||
#define G3D_Crypto_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/System.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** See G3D::Crypto::md5 */
|
||||
class MD5Hash {
|
||||
private:
|
||||
|
||||
uint8 value[16];
|
||||
|
||||
public:
|
||||
|
||||
MD5Hash() {
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
value[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
explicit MD5Hash(class BinaryInput& b);
|
||||
|
||||
/** Rotates the bytes once */
|
||||
void rotateBytes() {
|
||||
uint8 temp = value[0];
|
||||
for (int i = 0; i < 15; ++i) {
|
||||
value[i] = value[i + 1];
|
||||
}
|
||||
value[15] = temp;
|
||||
}
|
||||
|
||||
/** Rotates by n bytes */
|
||||
void rotateBytes(int n) {
|
||||
uint8 temp[16];
|
||||
System::memcpy(temp, value, 16);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
value[i] = value[(i + n) & 15];
|
||||
}
|
||||
}
|
||||
|
||||
uint8& operator[](int i) {
|
||||
return value[i];
|
||||
}
|
||||
|
||||
const uint8& operator[](int i) const {
|
||||
return value[i];
|
||||
}
|
||||
|
||||
bool operator==(const MD5Hash& other) const {
|
||||
bool match = true;
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
match = match && (other.value[i] == value[i]);
|
||||
}
|
||||
return match;
|
||||
}
|
||||
|
||||
inline bool operator!=(const MD5Hash& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
static size_t hashCode(const MD5Hash& key) {
|
||||
size_t h = 0;
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
const int x = i * 4;
|
||||
h ^= (((uint32)key.value[x + 0]) << 24) |
|
||||
(((uint32)key.value[x + 1]) << 16) |
|
||||
(((uint32)key.value[x + 2]) << 8) |
|
||||
((uint32)key.value[x + 3]);
|
||||
}
|
||||
return h;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** 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);
|
||||
|
||||
/**
|
||||
Computes the MD5 hash (message digest) of a byte stream, as defined by
|
||||
http://www.ietf.org/rfc/rfc1321.txt.
|
||||
|
||||
@cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com
|
||||
*/
|
||||
static MD5Hash md5(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
|
||||
92
dep/g3dlite/include/G3D/Cylinder.h
Normal file
92
dep/g3dlite/include/G3D/Cylinder.h
Normal file
@@ -0,0 +1,92 @@
|
||||
/**
|
||||
@file Cylinder.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-07
|
||||
@edited 2005-09-26
|
||||
|
||||
Copyright 2000-2005, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Cylinder_H
|
||||
#define G3D_Cylinder_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Line;
|
||||
class AABox;
|
||||
/**
|
||||
Right cylinder
|
||||
*/
|
||||
class Cylinder {
|
||||
private:
|
||||
Vector3 p1;
|
||||
Vector3 p2;
|
||||
|
||||
float mRadius;
|
||||
|
||||
public:
|
||||
|
||||
/** Uninitialized */
|
||||
Cylinder();
|
||||
Cylinder(class BinaryInput& b);
|
||||
Cylinder(const Vector3& _p1, const Vector3& _p2, float _r);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** The line down the center of the Cylinder */
|
||||
Line axis() const;
|
||||
|
||||
/**
|
||||
A reference frame in which the center of mass is at the origin and
|
||||
the Y-axis is the cylinder's axis. If the cylinder is transformed, this reference frame
|
||||
may freely rotate around its axis.*/
|
||||
void getReferenceFrame(class CoordinateFrame& cframe) const;
|
||||
|
||||
/** Returns point 0 or 1 */
|
||||
inline const Vector3& point(int i) const {
|
||||
debugAssert(i >= 0 && i <= 1);
|
||||
return (i == 0) ? p1 : p2;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the point is inside the Cylinder or on its surface.
|
||||
*/
|
||||
bool contains(const Vector3& p) const;
|
||||
|
||||
float area() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
float radius() const;
|
||||
|
||||
/** Center of mass */
|
||||
inline Vector3 center() const {
|
||||
return (p1 + p2) / 2.0f;
|
||||
}
|
||||
|
||||
inline float height() const {
|
||||
return (p1 - p2).magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
Get close axis aligned bounding box.
|
||||
With vertical world orientation, the top and bottom might not be very tight. */
|
||||
void getBounds(AABox& out) const;
|
||||
|
||||
/** Random world space point with outward facing normal. */
|
||||
void getRandomSurfacePoint(Vector3& P, Vector3& N) const;
|
||||
|
||||
/** Point selected uniformly at random over the volume. */
|
||||
Vector3 randomInteriorPoint() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
26
dep/g3dlite/include/G3D/EqualsTrait.h
Normal file
26
dep/g3dlite/include/G3D/EqualsTrait.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
@file EqualsTrait.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2008-10-01
|
||||
@edited 2008-10-01
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_EQUALSTRAIT_H
|
||||
#define G3D_EQUALSTRAIT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
/** Default implementation of EqualsTrait.
|
||||
@see G3D::Table for specialization requirements.
|
||||
*/
|
||||
template<typename Key> struct EqualsTrait {
|
||||
static bool equals(const Key& a, const Key& b) {
|
||||
return a == b;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
32
dep/g3dlite/include/G3D/FileNotFound.h
Normal file
32
dep/g3dlite/include/G3D/FileNotFound.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/**
|
||||
\file FileNotFound.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
\created 2011-12-31
|
||||
\edited 2011-12-31
|
||||
*/
|
||||
#ifndef G3D_FileNotFound_h
|
||||
#define G3D_FileNotFound_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Thrown by various file opening routines if the file is not found.
|
||||
|
||||
\sa ParseError, System::findDataFile
|
||||
*/
|
||||
class FileNotFound {
|
||||
public:
|
||||
std::string filename;
|
||||
std::string message;
|
||||
|
||||
FileNotFound() {}
|
||||
FileNotFound(const std::string& f, const std::string& m) : filename(f), message(m) {}
|
||||
virtual ~FileNotFound(){};
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
607
dep/g3dlite/include/G3D/FileSystem.h
Normal file
607
dep/g3dlite/include/G3D/FileSystem.h
Normal file
@@ -0,0 +1,607 @@
|
||||
/**
|
||||
\file FileSystem.h
|
||||
|
||||
\author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\author 2002-06-06
|
||||
\edited 2012-03-26
|
||||
*/
|
||||
#ifndef G3D_FileSystem_h
|
||||
#define G3D_FileSystem_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/Set.h"
|
||||
#include "G3D/GMutex.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
OS-independent file system layer that optimizes the performance
|
||||
of queries by caching and prefetching.
|
||||
|
||||
This class uses the following definitions:
|
||||
<ul>
|
||||
<li> "file" = document that can be opened for reading or writing
|
||||
<li> "directory" = folder containing files and other directories
|
||||
<li> "node" = file or directory
|
||||
<li> "path" = string identifying a (see the FSPath class)
|
||||
<li> "zipfile" = a compressed file storing an archive of files and directories in the zip format
|
||||
</ul>
|
||||
|
||||
In G3D, Zipfiles are transparently treated as if they were directories, provided:
|
||||
<ul>
|
||||
<li> The zipfile name contains an extension (e.g., map.pk3, files.zip)
|
||||
<li> There are no nested zipfiles
|
||||
</ul>
|
||||
|
||||
All FileSystem routines invoke FilePath::expandEnvironmentVariables if the input contains a '$'.
|
||||
|
||||
The extension requirement allows G3D to quickly identify whether a path could enter a
|
||||
zipfile without forcing it to open all parent directories for reading.
|
||||
|
||||
\sa FilePath
|
||||
*/
|
||||
class FileSystem {
|
||||
public:
|
||||
|
||||
class ListSettings {
|
||||
public:
|
||||
/** Defaults to true */
|
||||
bool files;
|
||||
|
||||
/** Defaults to true */
|
||||
bool directories;
|
||||
|
||||
/** Defaults to true on Windows, false on other platforms.*/
|
||||
bool caseSensitive;
|
||||
|
||||
/** Can get recurse into subdirectories? Defaults to true. */
|
||||
bool recursive;
|
||||
|
||||
/** Prefix the full path onto names that are returned. Defaults to true */
|
||||
bool includeParentPath;
|
||||
|
||||
ListSettings() :
|
||||
files(true),
|
||||
directories(true),
|
||||
# ifdef G3D_WINDOWS
|
||||
caseSensitive(true),
|
||||
# else
|
||||
caseSensitive(false),
|
||||
# endif
|
||||
recursive(false),
|
||||
includeParentPath(true) {}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** Drive letters. Only used on windows, but defined on all platforms to help
|
||||
avoid breaking the Windows build when compiling on another platform. */
|
||||
Array<std::string> m_winDrive;
|
||||
|
||||
float m_cacheLifetime;
|
||||
|
||||
enum Type {
|
||||
/** Not yet checked */
|
||||
UNKNOWN,
|
||||
FILE_TYPE,
|
||||
DIR_TYPE
|
||||
};
|
||||
|
||||
class Entry {
|
||||
public:
|
||||
/** Name, not including parent path */
|
||||
std::string name;
|
||||
Type type;
|
||||
Entry() : type(UNKNOWN) {}
|
||||
Entry(const char* n) : name(n), type(UNKNOWN) {}
|
||||
};
|
||||
|
||||
class Dir {
|
||||
public:
|
||||
|
||||
/** If false, this path did not exist (even inside a zipfile) when last checked, or it is not a directory. */
|
||||
bool exists;
|
||||
|
||||
bool isZipfile;
|
||||
bool inZipfile;
|
||||
|
||||
/** Files and directories */
|
||||
Array<Entry> nodeArray;
|
||||
|
||||
/** When this entry was last updated */
|
||||
double lastChecked;
|
||||
|
||||
bool contains(const std::string& child, bool caseSensitive =
|
||||
#ifdef G3D_WINDOWS
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
) const;
|
||||
|
||||
/** Compute the contents of nodeArray from this zipfile. */
|
||||
void computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile);
|
||||
|
||||
Dir() : exists(false), isZipfile(false), inZipfile(false), lastChecked(0) {}
|
||||
};
|
||||
|
||||
/** Maps path names (without trailing slashes, except for the file system root) to contents.
|
||||
On Windows, all paths are lowercase */
|
||||
Table<std::string, Dir> m_cache;
|
||||
|
||||
/** Update the cache entry for path if it is not already present.
|
||||
\param forceUpdate If true, always override the current cache value.*/
|
||||
Dir& getContents(const std::string& path, bool forceUpdate);
|
||||
|
||||
/** Don't allow public construction. */
|
||||
FileSystem();
|
||||
|
||||
static FileSystem& instance();
|
||||
static GMutex mutex;
|
||||
|
||||
|
||||
# ifdef G3D_WINDOWS
|
||||
/** \copydoc drives */
|
||||
const Array<std::string>& _drives();
|
||||
# endif
|
||||
|
||||
/** \copydoc inZipfile */
|
||||
bool _inZipfile(const std::string& path, std::string& zipfile);
|
||||
|
||||
/** \copydoc clearCache */
|
||||
void _clearCache(const std::string& path);
|
||||
|
||||
/** \copydoc inZipfile */
|
||||
bool _inZipfile(const std::string& path) {
|
||||
std::string ignore;
|
||||
return inZipfile(path, ignore);
|
||||
}
|
||||
|
||||
/** \copydoc setCacheLifetime */
|
||||
void _setCacheLifetime(float t);
|
||||
|
||||
|
||||
/** \copydoc cacheLifetime */
|
||||
float _cacheLifetime() const {
|
||||
return m_cacheLifetime;
|
||||
}
|
||||
|
||||
/** \copydoc createDirectory */
|
||||
void _createDirectory(const std::string& path);
|
||||
|
||||
/** \copydoc exists */
|
||||
bool _exists(const std::string& f, bool trustCache = true, bool caseSensitive =
|
||||
#ifdef G3D_WINDOWS
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
/** \copydoc isDirectory */
|
||||
bool _isDirectory(const std::string& path);
|
||||
|
||||
/** \copydoc isFile */
|
||||
bool _isFile(const std::string& path) {
|
||||
return ! isDirectory(path);
|
||||
}
|
||||
|
||||
/** \copydoc copyFile */
|
||||
void _copyFile(const std::string& srcPath, const std::string& dstPath);
|
||||
|
||||
/** \copydoc resolve */
|
||||
std::string _resolve(const std::string& path, const std::string& cwd = currentDirectory());
|
||||
|
||||
/** \copydoc isNewer */
|
||||
bool _isNewer(const std::string& src, const std::string& dst);
|
||||
|
||||
/** \copydoc currentDirectory */
|
||||
std::string _currentDirectory();
|
||||
|
||||
/** \copydoc size */
|
||||
int64 _size(const std::string& path);
|
||||
|
||||
/** Called from list() */
|
||||
void listHelper(const std::string& shortSpec, const std::string& parentPath, Array<std::string>& result, const ListSettings& settings);
|
||||
|
||||
/** \copydoc list */
|
||||
void _list(const std::string& spec, Array<std::string>& result, const ListSettings& listSettings = ListSettings());
|
||||
|
||||
/** \copydoc isZipfile */
|
||||
bool _isZipfile(const std::string& path);
|
||||
|
||||
/** \copydoc getFiles */
|
||||
void _getFiles(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
|
||||
ListSettings set;
|
||||
set.includeParentPath = includeParentPath;
|
||||
set.directories = false;
|
||||
set.files = true;
|
||||
return list(spec, result, set);
|
||||
}
|
||||
|
||||
/** \copydoc getDirectories */
|
||||
void _getDirectories(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
|
||||
ListSettings set;
|
||||
set.includeParentPath = includeParentPath;
|
||||
set.directories = true;
|
||||
set.files = false;
|
||||
return list(spec, result, set);
|
||||
}
|
||||
|
||||
/** \copydoc fopen */
|
||||
FILE* _fopen(const char* filename, const char* mode);
|
||||
|
||||
/** \copydoc removeFile */
|
||||
void _removeFile(const std::string& path);
|
||||
|
||||
public:
|
||||
|
||||
/** Create the common instance. */
|
||||
static void init();
|
||||
|
||||
/** Destroy the common instance. */
|
||||
static void cleanup();
|
||||
|
||||
# ifdef G3D_WINDOWS
|
||||
/** On Windows, the drive letters that form the file system roots.*/
|
||||
static const Array<std::string>& drives() {
|
||||
mutex.lock();
|
||||
const Array<std::string>& s = instance()._drives();
|
||||
mutex.unlock();
|
||||
return s;
|
||||
}
|
||||
# endif
|
||||
|
||||
/** Returns true if some sub-path of \a path is a zipfile.
|
||||
|
||||
If the path itself is a zipfile, returns false.
|
||||
|
||||
\param zipfile The part of \a path that was the zipfile
|
||||
*/
|
||||
static bool inZipfile(const std::string& path, std::string& zipfile) {
|
||||
mutex.lock();
|
||||
bool b = instance()._inZipfile(path, zipfile);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
/** Clears old cache entries so that exists() and list() will reflect recent changes to the file system.
|
||||
\param path Clear only \a path and its subdirectories ("" means clear the entire cache) */
|
||||
static void clearCache(const std::string& path = "") {
|
||||
mutex.lock();
|
||||
instance()._clearCache(path);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** Same as the C standard library fopen, but updates the file cache
|
||||
to acknowledge the new file on a write operation. */
|
||||
static FILE* fopen(const char* filename, const char* mode) {
|
||||
mutex.lock();
|
||||
FILE* f = instance()._fopen(filename, mode);
|
||||
mutex.unlock();
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
static void fclose(FILE* f) {
|
||||
mutex.lock();
|
||||
::fclose(f);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
/** Returns true if some sub-path of \a path is a zipfile.
|
||||
|
||||
If the path itself is a zipfile, returns false.
|
||||
*/
|
||||
static bool inZipfile(const std::string& path) {
|
||||
mutex.lock();
|
||||
bool b = instance()._inZipfile(path);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Delete this file.
|
||||
No effect if \a path does not exist.
|
||||
|
||||
\param path May contain wildcards. May not be inside a zipfile.
|
||||
*/
|
||||
static void removeFile(const std::string& path) {
|
||||
mutex.lock();
|
||||
instance()._removeFile(path);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if \a path is a file that is a zipfile. Note that G3D requires zipfiles to have
|
||||
some extension, although it is not required to be "zip" */
|
||||
static bool isZipfile(const std::string& path) {
|
||||
mutex.lock();
|
||||
bool b = instance()._isZipfile(path);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/** Set the cacheLifetime().
|
||||
\param t in seconds */
|
||||
void setCacheLifetime(float t) {
|
||||
mutex.lock();
|
||||
instance()._setCacheLifetime(t);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
/** A cache is used to optimize repeated calls. A cache entry is considered
|
||||
valid for this many seconds after it has been checked. */
|
||||
static float cacheLifetime() {
|
||||
mutex.lock();
|
||||
float f = instance()._cacheLifetime();
|
||||
mutex.unlock();
|
||||
return f;
|
||||
}
|
||||
|
||||
|
||||
/** Creates the directory named, including any subdirectories
|
||||
that do not already exist.
|
||||
|
||||
The directory must not be inside a zipfile.
|
||||
|
||||
Flushes the cache.
|
||||
*/
|
||||
static void createDirectory(const std::string& path) {
|
||||
mutex.lock();
|
||||
instance()._createDirectory(path);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** The current working directory (cwd). Only ends in a slash if this is the root of the file system. */
|
||||
static std::string currentDirectory() {
|
||||
mutex.lock();
|
||||
const std::string& s = instance()._currentDirectory();
|
||||
mutex.unlock();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\param srcPath Must name a file.
|
||||
\param dstPath Must not contain a zipfile.
|
||||
|
||||
Flushes the cache.
|
||||
*/
|
||||
static void copyFile(const std::string& srcPath, const std::string& dstPath) {
|
||||
mutex.lock();
|
||||
instance()._copyFile(srcPath, dstPath);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Returns true if a node named \a f exists.
|
||||
|
||||
\param f If \a f contains wildcards, the function returns true if any file
|
||||
matches those wildcards. Wildcards may only appear in the base or ext, not the
|
||||
path. Environment variables beginning with dollar signs (e.g., in "$G3DDATA/cubemap"),
|
||||
with optional parens ("$(G3DDATA)") are
|
||||
automatically expanded in \a f. Default share names on Windows (e.g., "\\mycomputer\c$")
|
||||
are correctly distinguished from empty environment variables.
|
||||
|
||||
\param trustCache If true, uses the cache for optimizing repeated calls
|
||||
in the same parent directory.
|
||||
|
||||
\param caseSensitive If true, the match must have exactly the same case for the base and extension. If false,
|
||||
case is ignored. The default on Windows is false and the default on other operating systems is true.
|
||||
*/
|
||||
static bool exists(const std::string& f, bool trustCache = true, bool caseSensitive =
|
||||
#ifdef G3D_WINDOWS
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
) {
|
||||
mutex.lock();
|
||||
bool e = instance()._exists(f, trustCache, caseSensitive);
|
||||
mutex.unlock();
|
||||
return e;
|
||||
}
|
||||
|
||||
|
||||
/** Known bug: does not work inside zipfiles */
|
||||
static bool isDirectory(const std::string& path) {
|
||||
mutex.lock();
|
||||
bool b = instance()._isDirectory(path);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/** Known bug: does not work inside zipfiles */
|
||||
static bool isFile(const std::string& path) {
|
||||
mutex.lock();
|
||||
bool b = instance()._isFile(path);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/** Fully qualifies a filename.
|
||||
|
||||
The filename may contain wildcards, in which case the wildcards will be preserved in the returned value.
|
||||
|
||||
\param cwd The directory to treat as the "current" directory when resolving a relative path. The default
|
||||
value is the actual current directory. (G3D::Any::sourceDirectory is a common alternative)
|
||||
*/
|
||||
static std::string resolve(const std::string& path, const std::string& cwd = currentDirectory()) {
|
||||
mutex.lock();
|
||||
const std::string& s = instance()._resolve(path, cwd);
|
||||
mutex.unlock();
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
/** Returns true if \a dst does not exist or \a src is newer than \a dst,
|
||||
according to their time stamps.
|
||||
|
||||
Known bug: does not work inside zipfiles.
|
||||
*/
|
||||
static bool isNewer(const std::string& src, const std::string& dst) {
|
||||
mutex.lock();
|
||||
bool b = instance()._isNewer(src, dst);
|
||||
mutex.unlock();
|
||||
return b;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the length of the file in bytes, or -1 if the file could not be opened. */
|
||||
static int64 size(const std::string& path) {
|
||||
mutex.lock();
|
||||
int64 i = instance()._size(path);
|
||||
mutex.unlock();
|
||||
return i;
|
||||
}
|
||||
|
||||
|
||||
/** Appends all nodes matching \a spec to the \a result array.
|
||||
|
||||
Wildcards can only appear to the right of the last slash in \a spec.
|
||||
|
||||
The names will not contain parent paths unless \a includePath == true.
|
||||
These may be relative to the current directory unless \a spec
|
||||
is fully qualified (can be done with resolveFilename).
|
||||
|
||||
*/
|
||||
static void list(const std::string& spec, Array<std::string>& result,
|
||||
const ListSettings& listSettings = ListSettings()) {
|
||||
mutex.lock();
|
||||
instance()._list(spec, result, listSettings);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** list() files */
|
||||
static void getFiles(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
|
||||
mutex.lock();
|
||||
instance()._getFiles(spec, result, includeParentPath);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
|
||||
/** list() directories */
|
||||
static void getDirectories(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
|
||||
mutex.lock();
|
||||
instance()._getDirectories(spec, result, includeParentPath);
|
||||
mutex.unlock();
|
||||
}
|
||||
|
||||
/** Adds \a filename to usedFiles(). This is called automatically by open() and all
|
||||
G3D routines that open files. */
|
||||
static void markFileUsed(const std::string& filename);
|
||||
|
||||
/** All files that have been marked by markFileUsed(). GApp automatically prints this list to log.txt. It is useful
|
||||
for finding the dependencies of your program automatically.*/
|
||||
static const Set<std::string>& usedFiles();
|
||||
};
|
||||
|
||||
|
||||
/** \brief Parsing of file system paths.
|
||||
|
||||
None of these routines touch the disk--they are purely string manipulation.
|
||||
|
||||
In "/a/b/base.ext",
|
||||
|
||||
<ul>
|
||||
<li> base = "base"
|
||||
<li> ext = "ext"
|
||||
<li> parentPath = "/a/b"
|
||||
<li> baseExt = "base.ext"
|
||||
</ul>
|
||||
|
||||
*/
|
||||
class FilePath {
|
||||
public:
|
||||
|
||||
/** Appends file onto dirname, ensuring a / if needed. */
|
||||
static std::string concat(const std::string& a, const std::string& b);
|
||||
|
||||
/** Returns true if \a f specifies a path that parses as root of the filesystem.
|
||||
On OS X and other Unix-based operating systems, "/" is the only root.
|
||||
On Windows, drive letters and shares are roots, e.g., "c:\", "\\foo\".
|
||||
Does not check on Windows to see if the root is actually mounted or a legal
|
||||
drive letter--this is a purely string based test. */
|
||||
static bool isRoot(const std::string& f);
|
||||
|
||||
/** Removes the trailing slash unless \a f is a filesystem root */
|
||||
static std::string removeTrailingSlash(const std::string& f);
|
||||
|
||||
/** Returns everything to the right of the last '.' */
|
||||
static std::string ext(const std::string& path);
|
||||
|
||||
/** Returns everything to the right of the last slash (or, on Windows, the last ':') */
|
||||
static std::string baseExt(const std::string& path);
|
||||
|
||||
/** Returns everything between the right-most slash and the following '.' */
|
||||
static std::string base(const std::string& path);
|
||||
|
||||
/** Returns everything to the left of the right-most slash */
|
||||
static std::string parent(const std::string& path);
|
||||
|
||||
/** Returns true if '*' or '?' appear in the filename */
|
||||
static bool containsWildcards(const std::string& p);
|
||||
|
||||
/** Convert all slashes to '/' */
|
||||
static std::string canonicalize(std::string x);
|
||||
|
||||
/** \brief Replaces <code>$VAR</code> and <code>$(VAR)</code> patterns with the corresponding environment variable.
|
||||
Throws std::string if the environment variable is not defined.
|
||||
*/
|
||||
static std::string expandEnvironmentVariables(const std::string& path);
|
||||
|
||||
/**
|
||||
Parses a filename into four useful pieces.
|
||||
|
||||
Examples:
|
||||
|
||||
c:\\a\\b\\d.e
|
||||
root = "c:\\"
|
||||
path = "a" "b"
|
||||
base = "d"
|
||||
ext = "e"
|
||||
|
||||
/a/b/d.e
|
||||
root = "/"
|
||||
path = "a" "b"
|
||||
base = "d"
|
||||
ext = "e"
|
||||
|
||||
/a/b
|
||||
root = "/"
|
||||
path = "a"
|
||||
base = "b"
|
||||
ext = "e"
|
||||
|
||||
*/
|
||||
static void parse
|
||||
(const std::string& filename,
|
||||
std::string& drive,
|
||||
Array<std::string>& path,
|
||||
std::string& base,
|
||||
std::string& ext);
|
||||
|
||||
/**
|
||||
Returns true if \a path matches \a pattern, with standard filesystem wildcards.
|
||||
*/
|
||||
static bool matches(const std::string& path, const std::string& pattern, bool caseSensitive = true);
|
||||
|
||||
/** Replaces characters that are illegal in a filename with legal equivalents.*/
|
||||
static std::string makeLegalFilename(const std::string& f, size_t maxLength = 100000);
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
#endif
|
||||
|
||||
57
dep/g3dlite/include/G3D/Frustum.h
Normal file
57
dep/g3dlite/include/G3D/Frustum.h
Normal file
@@ -0,0 +1,57 @@
|
||||
/**
|
||||
\file G3D/Frustum.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2005-07-20
|
||||
\edited 2013-06-11
|
||||
*/
|
||||
|
||||
#ifndef G3D_Frustum_h
|
||||
#define G3D_Frustum_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
#include "G3D/Vector4.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Box;
|
||||
|
||||
/** \see Projection */
|
||||
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. The order is that of
|
||||
the near face, starting from the (object space) +x,+y corner
|
||||
and proceeding CCW from the camera's point of view; followed
|
||||
by the far face also in CCW order.
|
||||
|
||||
If w == 0,
|
||||
a vertex is at infinity. */
|
||||
SmallArray<Vector4, 8> 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].
|
||||
*/
|
||||
SmallArray<Face, 6> faceArray;
|
||||
|
||||
/** \param minObjectSpaceDepth Smallest value permitted for the near plane Z - far plane Z (e.g., to force finite bounds)*/
|
||||
Box boundingBox(float minObjectSpaceDepth = finf()) const;
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
228
dep/g3dlite/include/G3D/G3D.h
Normal file
228
dep/g3dlite/include/G3D/G3D.h
Normal file
@@ -0,0 +1,228 @@
|
||||
/**
|
||||
\file G3D.h
|
||||
|
||||
This header includes all of the G3D libraries in
|
||||
appropriate namespaces.
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-08-25
|
||||
\edited 2013-03-24
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_G3D_h
|
||||
#define G3D_G3D_h
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX 1
|
||||
#endif
|
||||
#ifdef min
|
||||
#undef min
|
||||
#endif
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#include "G3D/HaltonSequence.h"
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Proxy.h"
|
||||
#include "G3D/BIN.h"
|
||||
#include "G3D/FileNotFound.h"
|
||||
#include "G3D/units.h"
|
||||
#include "G3D/ParseError.h"
|
||||
#include "G3D/Random.h"
|
||||
#include "G3D/Noise.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
#include "G3D/Queue.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include "G3D/format.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/Vector2int32.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/Vector2unorm16.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector3int16.h"
|
||||
#include "G3D/Vector3int32.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector4int16.h"
|
||||
#include "G3D/Vector4int8.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/Matrix2.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Projection.h"
|
||||
#include "G3D/PhysicsFrame.h"
|
||||
#include "G3D/PhysicsFrameSpline.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/Line.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/Sphere.h"
|
||||
#include "G3D/Box.h"
|
||||
#include "G3D/Box2D.h"
|
||||
#include "G3D/AABox.h"
|
||||
#include "G3D/WrapMode.h"
|
||||
#include "G3D/CullFace.h"
|
||||
#include "G3D/Cone.h"
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/prompt.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/FileSystem.h"
|
||||
#include "G3D/Set.h"
|
||||
#include "G3D/GUniqueID.h"
|
||||
#include "G3D/RayGridIterator.h"
|
||||
#include "G3D/BinaryFormat.h"
|
||||
#include "G3D/BinaryInput.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/g3dfnmatch.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/unorm8.h"
|
||||
#include "G3D/unorm16.h"
|
||||
#include "G3D/snorm8.h"
|
||||
#include "G3D/snorm16.h"
|
||||
#include "G3D/uint128.h"
|
||||
#include "G3D/fileutils.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/Welder.h"
|
||||
#include "G3D/GMutex.h"
|
||||
#include "G3D/PrecomputedRandom.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include "G3D/BlockPoolMemoryManager.h"
|
||||
#include "G3D/AreaMemoryManager.h"
|
||||
#include "G3D/BumpMapPreprocess.h"
|
||||
#include "G3D/CubeFace.h"
|
||||
#include "G3D/Line2D.h"
|
||||
#include "G3D/ThreadsafeQueue.h"
|
||||
#include "G3D/network.h"
|
||||
|
||||
template<class T> struct HashTrait< shared_ptr<T> > {
|
||||
static size_t hashCode(shared_ptr<T> key) { return reinterpret_cast<size_t>( key.get() ); }
|
||||
};
|
||||
|
||||
#include "G3D/Image.h"
|
||||
#include "G3D/CollisionDetection.h"
|
||||
#include "G3D/Intersect.h"
|
||||
#include "G3D/Log.h"
|
||||
#include "G3D/serialize.h"
|
||||
#include "G3D/TextInput.h"
|
||||
#include "G3D/NetAddress.h"
|
||||
#include "G3D/NetworkDevice.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/splinefunc.h"
|
||||
#include "G3D/Spline.h"
|
||||
#include "G3D/UprightFrame.h"
|
||||
#include "G3D/LineSegment.h"
|
||||
#include "G3D/Capsule.h"
|
||||
#include "G3D/Cylinder.h"
|
||||
#include "G3D/Triangle.h"
|
||||
#include "G3D/Color1unorm8.h"
|
||||
#include "G3D/Color2unorm8.h"
|
||||
#include "G3D/Color3unorm8.h"
|
||||
#include "G3D/Color4unorm8.h"
|
||||
#include "G3D/ConvexPolyhedron.h"
|
||||
#include "G3D/MeshAlg.h"
|
||||
#include "G3D/vectorMath.h"
|
||||
#include "G3D/Rect2D.h"
|
||||
#include "G3D/KDTree.h"
|
||||
#include "G3D/PointKDTree.h"
|
||||
#include "G3D/TextOutput.h"
|
||||
#include "G3D/MeshBuilder.h"
|
||||
#include "G3D/Stopwatch.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/GThread.h"
|
||||
#include "G3D/ThreadSet.h"
|
||||
#include "G3D/RegistryUtil.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/XML.h"
|
||||
#include "G3D/PointHashGrid.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Image1.h"
|
||||
#include "G3D/Image1unorm8.h"
|
||||
#include "G3D/Image3.h"
|
||||
#include "G3D/Image3unorm8.h"
|
||||
#include "G3D/Image4.h"
|
||||
#include "G3D/Image4unorm8.h"
|
||||
#include "G3D/filter.h"
|
||||
#include "G3D/WeakCache.h"
|
||||
#include "G3D/Pointer.h"
|
||||
#include "G3D/Matrix.h"
|
||||
#include "G3D/ImageFormat.h"
|
||||
#include "G3D/PixelTransferBuffer.h"
|
||||
#include "G3D/typeutils.h"
|
||||
#include "G3D/SpeedLoad.h"
|
||||
#include "G3D/ParseMTL.h"
|
||||
#include "G3D/ParseOBJ.h"
|
||||
#include "G3D/ParsePLY.h"
|
||||
#include "G3D/Parse3DS.h"
|
||||
#include "G3D/PathDirection.h"
|
||||
#include "G3D/FastPODTable.h"
|
||||
#include "G3D/FastPointHashGrid.h"
|
||||
#include "G3D/PixelTransferBuffer.h"
|
||||
#include "G3D/CPUPixelTransferBuffer.h"
|
||||
#include "G3D/CompassDirection.h"
|
||||
#include "G3D/Access.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Call from main() to initialize the G3D library state and register
|
||||
shutdown memory managers. This does not initialize OpenGL.
|
||||
|
||||
If you invoke initGLG3D, then it will automatically call initG3D.
|
||||
It is safe to call this function more than once--it simply ignores
|
||||
multiple calls.
|
||||
|
||||
\see System, GLCaps, OSWindow, RenderDevice, initGLG3D.
|
||||
|
||||
*/
|
||||
void initG3D(const G3DSpecification& spec = G3DSpecification());
|
||||
}
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma comment(lib, "winmm")
|
||||
# pragma comment(lib, "imagehlp")
|
||||
# pragma comment(lib, "ws2_32")
|
||||
# pragma comment(lib, "gdi32")
|
||||
# pragma comment(lib, "user32")
|
||||
# pragma comment(lib, "kernel32")
|
||||
# pragma comment(lib, "advapi32")
|
||||
# pragma comment(lib, "shell32")
|
||||
# pragma comment(lib, "version")
|
||||
# ifdef G3D_64BIT
|
||||
# pragma comment(lib, "zlib_x64")
|
||||
# pragma comment(lib, "zip_x64")
|
||||
# pragma comment(lib, "enet_x64")
|
||||
# else
|
||||
# pragma comment(lib, "zlib")
|
||||
# pragma comment(lib, "zip")
|
||||
# pragma comment(lib, "enet")
|
||||
# endif
|
||||
# if defined(_DEBUG)
|
||||
# ifdef G3D_64BIT
|
||||
# pragma comment(lib, "G3D_x64d")
|
||||
# pragma comment(lib, "freeimage_x64d")
|
||||
# else
|
||||
# pragma comment(lib, "G3Dd")
|
||||
# pragma comment(lib, "freeimaged")
|
||||
# endif
|
||||
# else
|
||||
# ifdef G3D_64BIT
|
||||
# pragma comment(lib, "G3D_x64")
|
||||
# pragma comment(lib, "freeimage_x64")
|
||||
# else
|
||||
# pragma comment(lib, "G3D")
|
||||
# pragma comment(lib, "freeimage")
|
||||
# endif
|
||||
# endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
26
dep/g3dlite/include/G3D/G3DAll.h
Normal file
26
dep/g3dlite/include/G3D/G3DAll.h
Normal file
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
@file G3DAll.h
|
||||
|
||||
Includes all G3D and GLG3D files and uses the G3D namespace.
|
||||
|
||||
This requires OpenGL and SDL headers. If you don't want all of this,
|
||||
\#include <G3D.h> separately.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-01-01
|
||||
@edited 2006-08-13
|
||||
|
||||
Copyright 2000-2006, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_G3DALL_H
|
||||
#define G3D_G3DALL_H
|
||||
|
||||
#include "G3D/G3D.h"
|
||||
#include "GLG3D/GLG3D.h"
|
||||
|
||||
using namespace G3D;
|
||||
|
||||
#endif
|
||||
45
dep/g3dlite/include/G3D/G3DGameUnits.h
Normal file
45
dep/g3dlite/include/G3D/G3DGameUnits.h
Normal file
@@ -0,0 +1,45 @@
|
||||
/**
|
||||
@file G3DGameUnits.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2002-10-05
|
||||
@edited 2012-02-19
|
||||
*/
|
||||
|
||||
#ifndef G3D_GAMEUNITS_H
|
||||
#define G3D_GAMEUNITS_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** \deprecated use SimTime */
|
||||
typedef double GameTime;
|
||||
|
||||
/**
|
||||
Time, in seconds.
|
||||
*/
|
||||
typedef double SimTime;
|
||||
|
||||
/**
|
||||
Actual wall clock time in seconds (Unix time).
|
||||
*/
|
||||
typedef double RealTime;
|
||||
|
||||
enum AMPM {AM, PM};
|
||||
|
||||
/** \deprecated */
|
||||
enum {SECOND=1, MINUTE=60, HOUR = 60*60, DAY=24*60*60, SUNRISE=24*60*60/4, SUNSET=24*60*60*3/4, MIDNIGHT=0, METER=1, KILOMETER=1000};
|
||||
|
||||
/**
|
||||
Converts a 12 hour clock time into the number of seconds since
|
||||
midnight. Note that 12:00 PM is noon and 12:00 AM is midnight.
|
||||
|
||||
Example: <CODE>toSeconds(10, 00, AM)</CODE>
|
||||
*/
|
||||
SimTime toSeconds(int hour, int minute, double seconds, AMPM ap);
|
||||
SimTime toSeconds(int hour, int minute, AMPM ap);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
354
dep/g3dlite/include/G3D/GCamera.h
Normal file
354
dep/g3dlite/include/G3D/GCamera.h
Normal file
@@ -0,0 +1,354 @@
|
||||
/**
|
||||
@file GCamera.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-07-20
|
||||
@edited 2009-04-20
|
||||
*/
|
||||
|
||||
#ifndef G3D_GCamera_H
|
||||
#define G3D_GCamera_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Plane.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Matrix4;
|
||||
class Rect2D;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
Abstraction of a pinhole camera.
|
||||
|
||||
The area a camera sees is called a frustum. It is bounded by the
|
||||
near plane, the far plane, and the sides of the view frame projected
|
||||
into the scene. It has the shape of a pyramid with the top cut off.
|
||||
|
||||
Cameras can project points from 3D to 2D. The "unit" projection
|
||||
matches OpenGL. It maps the entire view frustum to a cube of unit
|
||||
radius (i.e., edges of length 2) centered at the origin. The
|
||||
non-unit projection then maps that cube to the specified pixel
|
||||
viewport in X and Y and the range [0, 1] in Z. The projection is
|
||||
reversable as long as the projected Z value is known.
|
||||
|
||||
All viewport arguments are the pixel bounds of the viewport-- e.g.,
|
||||
RenderDevice::viewport().
|
||||
|
||||
See http://bittermanandy.wordpress.com/2009/04/10/a-view-to-a-thrill-part-one-camera-concepts/
|
||||
for a nice introduction to camera transformations.
|
||||
*/
|
||||
class GCamera {
|
||||
|
||||
public:
|
||||
/**
|
||||
Stores the direction of the field of view
|
||||
*/
|
||||
enum FOVDirection {HORIZONTAL, VERTICAL};
|
||||
|
||||
private:
|
||||
|
||||
/** Full field of view (in radians) */
|
||||
float m_fieldOfView;
|
||||
|
||||
/** Clipping plane, *not* imaging plane. Negative numbers. */
|
||||
float m_nearPlaneZ;
|
||||
|
||||
/** Negative */
|
||||
float m_farPlaneZ;
|
||||
|
||||
/** Stores the camera's location and orientation */
|
||||
CoordinateFrame m_cframe;
|
||||
|
||||
/** Horizontal or Vertical */
|
||||
FOVDirection m_direction;
|
||||
|
||||
Vector2 m_pixelOffset;
|
||||
|
||||
public:
|
||||
|
||||
/** Must be of the format produced by the Any cast, e.g.,
|
||||
|
||||
<pre>
|
||||
GCamera {
|
||||
coordinateFrame = CFrame::fromXYZYPRDegrees(-13.3f, 8.0f, -1.9f, 246.6f, -3),
|
||||
nearPlaneZ = -0.5,
|
||||
farPlaneZ = -50,
|
||||
fovDirection = "HORIZONTAL",
|
||||
fovAngleDegrees = 90
|
||||
}</pre>
|
||||
|
||||
Missing fields are filled from the default GCamera constructor.
|
||||
*/
|
||||
GCamera(const Any& any);
|
||||
|
||||
operator Any() const;
|
||||
|
||||
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();
|
||||
|
||||
GCamera(const Matrix4& proj, const CFrame& frame);
|
||||
|
||||
virtual ~GCamera();
|
||||
|
||||
/** Returns the current coordinate frame */
|
||||
const CoordinateFrame& coordinateFrame() const {
|
||||
return m_cframe;
|
||||
}
|
||||
|
||||
/** Displacement from the upper left added in pixels in screen
|
||||
space to the projection matrix. This is useful for shifting
|
||||
the sampled location from the pixel center (OpenGL convention)
|
||||
to other locations, such as the upper-left.*/
|
||||
void setPixelOffset(const Vector2& p) {
|
||||
m_pixelOffset = p;
|
||||
}
|
||||
|
||||
const Vector2& pixelOffset() const {
|
||||
return m_pixelOffset;
|
||||
}
|
||||
|
||||
/** Sets c to the camera's coordinate frame */
|
||||
void getCoordinateFrame(CoordinateFrame& c) const;
|
||||
|
||||
/** Sets a new coordinate frame for the camera */
|
||||
void setCoordinateFrame(const CoordinateFrame& c);
|
||||
|
||||
/** Sets \a P equal to the camera's projection matrix. This is the
|
||||
matrix that maps points to the homogeneous clip cube that
|
||||
varies from -1 to 1 on all axes. The projection matrix does
|
||||
not include the camera transform.
|
||||
|
||||
This is the matrix that a RenderDevice (or OpenGL) uses as the projection matrix.
|
||||
@sa RenderDevice::setProjectionAndCameraMatrix, RenderDevice::setProjectionMatrix, Matrix4::perspectiveProjection
|
||||
*/
|
||||
void getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const;
|
||||
|
||||
/** Sets \a P equal to the matrix that transforms points to pixel
|
||||
coordinates on the given viewport. A point correspoinding to
|
||||
the top-left corner of the viewport in camera space will
|
||||
transform to viewport.x0y0() and the bottom-right to viewport.x1y1(). */
|
||||
void getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const;
|
||||
|
||||
/** Converts projected points from OpenGL standards
|
||||
(-1, 1) to normal 3D coordinate standards (0, 1)
|
||||
|
||||
\deprecated
|
||||
*/ // TODO: Remove
|
||||
Vector3 convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Sets the field of view, in radians. The
|
||||
initial angle is toRadians(55). Must specify
|
||||
the direction of the angle.
|
||||
|
||||
This is the full angle, i.e., from the left side of the
|
||||
viewport to the right side.
|
||||
*/
|
||||
void setFieldOfView(float edgeToEdgeAngleRadians, FOVDirection direction);
|
||||
|
||||
/** Returns the current full field of view angle (from the left side of the
|
||||
viewport to the right side) and direction */
|
||||
inline void getFieldOfView(float& angle, FOVDirection& direction) const {
|
||||
angle = m_fieldOfView;
|
||||
direction = m_direction;
|
||||
}
|
||||
|
||||
/**
|
||||
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 0 at the near plane, 1 at the far plane,
|
||||
and is a linear compression of unit cube projection.
|
||||
|
||||
If the point is behind the camera, Vector3::inf() is returned.
|
||||
*/
|
||||
Vector3 project(const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Projects a world space point onto a unit cube. The resulting
|
||||
x,y,z values range between -1 and 1, where z is -1
|
||||
at the near plane and 1 at the far plane and varies hyperbolically in between.
|
||||
|
||||
If the point is behind the camera, Vector3::inf() is returned.
|
||||
*/
|
||||
Vector3 projectUnit(const G3D::Vector3& point,
|
||||
const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Gives the world-space coordinates of screen space point v, where
|
||||
v.x is in pixels from the left, v.y is in pixels from
|
||||
the top, and v.z is on the range 0 (near plane) to 1 (far plane).
|
||||
*/
|
||||
Vector3 unproject(const Vector3& v, const Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Gives the world-space coordinates of unit cube point v, where
|
||||
v varies from -1 to 1 on all axes. The unproject first
|
||||
transforms the point into a pixel location for the viewport, then calls unproject
|
||||
*/
|
||||
Vector3 unprojectUnit(const Vector3& v, const 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, viewportWidth, and viewportHeight.
|
||||
"left" and "right" are from the GCamera's perspective.
|
||||
*/
|
||||
void getNearViewportCorners(const class Rect2D& viewport,
|
||||
Vector3& outUR, Vector3& outUL,
|
||||
Vector3& outLL, Vector3& outLR) const;
|
||||
|
||||
/**
|
||||
Returns the world space 3D viewport corners. These
|
||||
are at the Far clipping plane. The corners are constructed
|
||||
from the nearPlaneZ, farPlaneZ, viewportWidth, and viewportHeight.
|
||||
"left" and "right" are from the GCamera's perspective.
|
||||
*/
|
||||
void getFarViewportCorners(const class Rect2D& viewport,
|
||||
Vector3& outUR, Vector3& outUL,
|
||||
Vector3& outLL, Vector3& outLR) const;
|
||||
|
||||
/**
|
||||
Returns the image plane depth, assumes imagePlane
|
||||
is the same as the near clipping plane.
|
||||
returns a positive number.
|
||||
*/
|
||||
float imagePlaneDepth() 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.
|
||||
|
||||
The ray origin is at the origin. To start it at the image plane,
|
||||
move it forward by imagePlaneDepth/ray.direction.z
|
||||
|
||||
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 nearPlaneZ() const {
|
||||
return m_nearPlaneZ;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a negative z-value.
|
||||
*/
|
||||
inline float farPlaneZ() const {
|
||||
return m_farPlaneZ;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets a new value for the far clipping plane
|
||||
Expects a negative value
|
||||
*/
|
||||
inline void setFarPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
m_farPlaneZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
Sets a new value for the near clipping plane
|
||||
Expects a negative value
|
||||
*/
|
||||
inline void setNearPlaneZ(float z) {
|
||||
debugAssert(z < 0);
|
||||
m_nearPlaneZ = z;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the camera space width of the viewport at the near plane.
|
||||
*/
|
||||
float viewportWidth(const class Rect2D& viewport) const;
|
||||
|
||||
/**
|
||||
Returns the camera space height of the viewport at the near plane.
|
||||
*/
|
||||
float viewportHeight(const class Rect2D& viewport) const;
|
||||
|
||||
void setPosition(const Vector3& t);
|
||||
|
||||
/** Rotate the camera in place to look at the target. Does not
|
||||
persistently look at that location when the camera moves;
|
||||
i.e., if you move the camera and still want it to look at the
|
||||
old target, you must call lookAt again after moving the
|
||||
camera.)*/
|
||||
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 frustum(const Rect2D& viewport, GCamera::Frustum& f) const;
|
||||
|
||||
GCamera::Frustum frustum(const Rect2D& viewport) const;
|
||||
|
||||
/** Read and Write camera parameters */
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
611
dep/g3dlite/include/G3D/GImage.h
Normal file
611
dep/g3dlite/include/G3D/GImage.h
Normal file
@@ -0,0 +1,611 @@
|
||||
/**
|
||||
\file GImage.h
|
||||
|
||||
See G3D::GImage for details.
|
||||
|
||||
@cite JPEG compress/decompressor is the <A HREF="http://www.ijg.org/files/">IJG library</A>, used in accordance with their license.
|
||||
@cite JPG code by John Chisholm, using the IJG Library
|
||||
@cite TGA code by Morgan McGuire
|
||||
@cite BMP code by John Chisholm, based on code by Edward "CGameProgrammer" Resnick <A HREF="mailto:cgp@gdnmail.net">mailto:cgp@gdnmail.net</A> at <A HREF="ftp://ftp.flipcode.com/cotd/LoadPicture.txt">ftp://ftp.flipcode.com/cotd/LoadPicture.txt</A>
|
||||
@cite PCX format described in the ZSOFT PCX manual http://www.nist.fss.ru/hr/doc/spec/pcx.htm#2
|
||||
@cite PNG compress/decompressor is the <A HREF="http://www.libpng.org/pub/png/libpng.html">libpng library</A>, used in accordance with their license.
|
||||
@cite PPM code by Morgan McGuire based on http://netpbm.sourceforge.net/doc/ppm.html
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2002-05-27
|
||||
\edited 2010-01-04
|
||||
|
||||
Copyright 2000-2010, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_GImage_h
|
||||
#define G3D_GImage_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include <string>
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/stringutils.h"
|
||||
#include "G3D/Color1uint8.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
#include "G3D/Color4uint8.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include "G3D/BumpMapPreprocess.h"
|
||||
|
||||
namespace G3D {
|
||||
class BinaryInput;
|
||||
class BinaryOutput;
|
||||
|
||||
|
||||
/**
|
||||
Interface to image compression & file formats.
|
||||
|
||||
Supported formats (decode and encode): Color JPEG, PNG,
|
||||
(Uncompressed) TGA 24, (Uncompressed) TGA 32, BMP 1, BMP 4, BMP 8, BMP
|
||||
24, PPM (P6), and PPM ASCII (P1, P2, P3), which includes PPM, PGM,
|
||||
and PBM. (Compressed) TGA 24, (Compressed) TGA 32, 8-bit paletted PCX, 24-bit PCX, and ICO are supported for
|
||||
decoding only.
|
||||
|
||||
Sample usage:
|
||||
|
||||
\verbatim
|
||||
// Loading from disk:
|
||||
G3D::GImage im1("test.jpg");
|
||||
|
||||
// Loading from memory:
|
||||
G3D::GImage im2(data, length);
|
||||
|
||||
// im.pixel is a pointer to RGB color data. If you want
|
||||
// an alpha channel, call RGBtoRGBA or RGBtoARGB for
|
||||
// conversion.
|
||||
|
||||
// Saving to memory:
|
||||
G3D::GImage im3(width, height);
|
||||
// (Set the pixels of im3...)
|
||||
uint8* data2;
|
||||
int len2;
|
||||
im3.encode(G3D::GImage::JPEG, data2, len2);
|
||||
|
||||
// Saving to disk
|
||||
im3.save("out.jpg");
|
||||
\endverbatim
|
||||
|
||||
The free Image Magick Magick Wand API
|
||||
(http://www.imagemagick.org/www/api/magick_wand.html) provides a more powerful
|
||||
API for image manipulation and wider set of image load/save formats. It is
|
||||
recommended over GImage (we don't include it directly in G3D because their license
|
||||
is more restrictive than the BSD one).
|
||||
|
||||
\cite http://tfcduke.developpez.com/tutoriel/format/tga/fichiers/tga_specs.pdf
|
||||
|
||||
\sa Image3, Image3uint8, Image4, Image4uint8, Image1, Image1uint8, Texture, Map2D
|
||||
|
||||
*/
|
||||
class GImage {
|
||||
private:
|
||||
|
||||
/** Used exclusively for allocating m_byte; this may be an
|
||||
implementation that allocates directly on a GPU.*/
|
||||
MemoryManager::Ref m_memMan;
|
||||
uint8* m_byte;
|
||||
|
||||
int m_channels;
|
||||
int m_width;
|
||||
int m_height;
|
||||
|
||||
public:
|
||||
|
||||
class Error {
|
||||
public:
|
||||
Error(
|
||||
const std::string& reason,
|
||||
const std::string& filename = "") :
|
||||
reason(reason), filename(filename) {}
|
||||
|
||||
std::string reason;
|
||||
std::string filename;
|
||||
};
|
||||
|
||||
/** PGM, PPM, and PBM all come in two versions and are classified as PPM_* files */
|
||||
enum Format {JPEG, BMP, TGA, PCX, ICO, PNG,
|
||||
PPM_BINARY, PGM_BINARY = PPM_BINARY,
|
||||
PPM_ASCII, PGM_ASCII = PPM_ASCII,
|
||||
AUTODETECT, UNKNOWN};
|
||||
|
||||
|
||||
/**
|
||||
The number of channels; either 3 (RGB) or 4 (RGBA)
|
||||
*/
|
||||
inline int channels() const {
|
||||
return m_channels;
|
||||
}
|
||||
|
||||
inline int width() const {
|
||||
return m_width;
|
||||
}
|
||||
|
||||
inline int height() const {
|
||||
return m_height;
|
||||
}
|
||||
|
||||
inline const uint8* byte() const {
|
||||
return m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the underlying data, which is stored
|
||||
in row-major order without row padding.
|
||||
e.g., <code>uint8* ptr = image.rawData<uint8>();
|
||||
*/
|
||||
template<typename Type>
|
||||
inline const Type* rawData() const {
|
||||
return (Type*)m_byte;
|
||||
}
|
||||
|
||||
/** \copybrief GImage::rawData() const */
|
||||
template<typename Type>
|
||||
inline Type* rawData() {
|
||||
return (Type*)m_byte;
|
||||
}
|
||||
|
||||
inline const Color1uint8* pixel1() const {
|
||||
debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
|
||||
return (Color1uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color1uint8* pixel1() {
|
||||
debugAssertM(m_channels == 1, format("Tried to call GImage::pixel1 on an image with %d channels", m_channels));
|
||||
return (Color1uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the upper left pixel
|
||||
as Color4uint8.
|
||||
*/
|
||||
inline const Color4uint8* pixel4() const {
|
||||
debugAssertM(m_channels == 4, format("Tried to call GImage::pixel4 on an image with %d channels", m_channels));
|
||||
return (Color4uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color4uint8* pixel4() {
|
||||
debugAssert(m_channels == 4);
|
||||
return (Color4uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the upper left pixel
|
||||
as Color3uint8.
|
||||
*/
|
||||
inline const Color3uint8* pixel3() const {
|
||||
debugAssertM(m_channels == 3, format("Tried to call GImage::pixel3 on an image with %d channels", m_channels));
|
||||
return (Color3uint8*)m_byte;
|
||||
}
|
||||
|
||||
inline Color3uint8* pixel3() {
|
||||
debugAssert(m_channels == 3);
|
||||
return (Color3uint8*)m_byte;
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color1uint8& pixel1(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel1()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline Color1uint8& pixel1(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel1()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color3uint8& pixel3(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel3()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline Color3uint8& pixel3(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel3()[x + y * m_width];
|
||||
}
|
||||
|
||||
/** Returns the pixel at (x, y), where (0,0) is the upper left. */
|
||||
inline const Color4uint8& pixel4(int x, int y) const {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel4()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline Color4uint8& pixel4(int x, int y) {
|
||||
debugAssert(x >= 0 && x < m_width);
|
||||
debugAssert(y >= 0 && y < m_height);
|
||||
return pixel4()[x + y * m_width];
|
||||
}
|
||||
|
||||
inline uint8* byte() {
|
||||
return m_byte;
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
void encodeBMP(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
The TGA file will be either 24- or 32-bit depending
|
||||
on the number of channels.
|
||||
*/
|
||||
void encodeTGA(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Converts this image into a JPEG
|
||||
*/
|
||||
void encodeJPEG(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Converts this image into a JPEG
|
||||
*/
|
||||
void encodePNG(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void encodePPM(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void encodePPMASCII(
|
||||
BinaryOutput& out) const;
|
||||
|
||||
void decodeTGA(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeBMP(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeJPEG(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePCX(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodeICO(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePNG(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePPM(
|
||||
BinaryInput& input);
|
||||
|
||||
void decodePPMASCII(
|
||||
BinaryInput& input);
|
||||
|
||||
/**
|
||||
Given [maybe] a filename, memory buffer, and [maybe] a format,
|
||||
returns the most likely format of this file.
|
||||
*/
|
||||
static Format resolveFormat(
|
||||
const std::string& filename,
|
||||
const uint8* data,
|
||||
int dataLen,
|
||||
Format maybeFormat);
|
||||
|
||||
void _copy(
|
||||
const GImage& other);
|
||||
|
||||
public:
|
||||
|
||||
/** Predicts the image file format of \a filename */
|
||||
static Format resolveFormat(const std::string& filename);
|
||||
|
||||
void flipHorizontal();
|
||||
void flipVertical();
|
||||
void rotate90CW(int numTimes = 1);
|
||||
|
||||
/**
|
||||
Create an empty image of the given size.
|
||||
\sa load()
|
||||
*/
|
||||
GImage(
|
||||
int width = 0,
|
||||
int height = 0,
|
||||
int channels = 3,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
/**
|
||||
Load an encoded image from disk and decode it.
|
||||
Throws GImage::Error if something goes wrong.
|
||||
*/
|
||||
GImage(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
/**
|
||||
Decodes an image stored in a buffer.
|
||||
*/
|
||||
GImage(
|
||||
const unsigned char*data,
|
||||
int length,
|
||||
Format format = AUTODETECT,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
GImage(
|
||||
const GImage& other,
|
||||
const MemoryManager::Ref& m = MemoryManager::create());
|
||||
|
||||
GImage& operator=(const GImage& other);
|
||||
|
||||
/**
|
||||
Returns a new GImage that has 4 channels. RGB is
|
||||
taken from this GImage and the alpha from the red
|
||||
channel of the supplied image. The new GImage is passed
|
||||
as a reference parameter for speed.
|
||||
*/
|
||||
void insertRedAsAlpha(const GImage& alpha, GImage& output) const;
|
||||
|
||||
/**
|
||||
Returns a new GImage with 3 channels, removing
|
||||
the alpha channel if there is one. The new GImage
|
||||
is passed as a reference parameter for speed.
|
||||
*/
|
||||
void stripAlpha(GImage& output) const;
|
||||
|
||||
/**
|
||||
Loads an image from disk (clearing the old one first),
|
||||
using the existing memory manager.
|
||||
*/
|
||||
void load(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT);
|
||||
|
||||
/**
|
||||
Frees memory and resets to a 0x0 image.
|
||||
*/
|
||||
void clear();
|
||||
|
||||
/**
|
||||
Deallocates the pixels.
|
||||
*/
|
||||
virtual ~GImage();
|
||||
|
||||
/**
|
||||
Resizes the internal buffer to (\a width x \a height) with the
|
||||
number of \a channels specified.
|
||||
|
||||
\param zero If true, all data is set to 0 (black).
|
||||
*/
|
||||
void resize(int width, int height, int channels, bool zero = true);
|
||||
|
||||
/**
|
||||
Copies src sub-image data into dest at a certain offset.
|
||||
The dest variable must already contain an image that is large
|
||||
enough to contain the src sub-image at the specified offset.
|
||||
Returns true on success and false if the src sub-image cannot
|
||||
completely fit within dest at the specified offset. Both
|
||||
src and dest must have the same number of channels.
|
||||
*/
|
||||
static bool pasteSubImage(
|
||||
GImage& dest,
|
||||
const GImage& src,
|
||||
int destX,
|
||||
int destY,
|
||||
int srcX,
|
||||
int srcY,
|
||||
int srcWidth,
|
||||
int srcHeight);
|
||||
|
||||
/**
|
||||
creates dest from src sub-image data.
|
||||
Returns true on success and false if the src sub-image
|
||||
is not within src.
|
||||
*/
|
||||
static bool copySubImage(GImage & dest, const GImage & src,
|
||||
int srcX, int srcY, int srcWidth, int srcHeight);
|
||||
|
||||
void convertToRGBA();
|
||||
|
||||
void convertToRGB();
|
||||
|
||||
/** Averages color channels if they exist */
|
||||
void convertToL8();
|
||||
|
||||
/**
|
||||
Returns true if format is supported. Format
|
||||
should be an extension string (e.g. "BMP").
|
||||
*/
|
||||
static bool supportedFormat(
|
||||
const std::string& format);
|
||||
|
||||
/**
|
||||
Converts a string to an enum, returns UNKNOWN if not recognized.
|
||||
*/
|
||||
static Format stringToFormat(
|
||||
const std::string& format);
|
||||
|
||||
/**
|
||||
Encode and save to disk.
|
||||
*/
|
||||
void save(
|
||||
const std::string& filename,
|
||||
Format format = AUTODETECT) const;
|
||||
|
||||
/**
|
||||
The caller must delete the returned buffer.
|
||||
TODO: provide a memory manager
|
||||
*/
|
||||
void encode(
|
||||
Format format,
|
||||
uint8*& outData,
|
||||
int& outLength) const;
|
||||
|
||||
/**
|
||||
Does not commit the BinaryOutput when done.
|
||||
*/
|
||||
void encode(
|
||||
Format format,
|
||||
BinaryOutput& out) const;
|
||||
|
||||
/**
|
||||
Decodes the buffer into this image.
|
||||
@param format Must be the correct format.
|
||||
*/
|
||||
void decode(
|
||||
BinaryInput& input,
|
||||
Format format);
|
||||
|
||||
/** Returns the size of this object in bytes */
|
||||
int sizeInMemory() const;
|
||||
|
||||
/** Ok for in == out */
|
||||
static void R8G8B8_to_Y8U8V8(int width, int height, const uint8* in, uint8* out);
|
||||
|
||||
/** Ok for in == out */
|
||||
static void Y8U8V8_to_R8G8B8(int width, int height, const uint8* in, uint8* out);
|
||||
|
||||
/**
|
||||
@param in RGB buffer of numPixels * 3 bytes
|
||||
@param out Buffer of numPixels * 4 bytes
|
||||
@param numPixels Number of RGB pixels to convert
|
||||
*/
|
||||
static void RGBtoRGBA(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void RGBtoARGB(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void LtoRGB
|
||||
(const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void LtoRGBA
|
||||
(const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/** Safe for in == out */
|
||||
static void RGBtoBGR(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/**
|
||||
Win32 32-bit HDC format.
|
||||
*/
|
||||
static void RGBtoBGRA(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
static void RGBAtoRGB(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
/**
|
||||
Uses the red channel of the second image as an alpha channel.
|
||||
*/
|
||||
static void RGBxRGBtoRGBA(
|
||||
const uint8* colorRGB,
|
||||
const uint8* alphaRGB,
|
||||
uint8* out,
|
||||
int numPixels);
|
||||
|
||||
/**
|
||||
Flips the image along the vertical axis.
|
||||
Safe for in == out.
|
||||
*/
|
||||
static void flipRGBVertical(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
static void flipRGBAVertical(
|
||||
const uint8* in,
|
||||
uint8* out,
|
||||
int width,
|
||||
int height);
|
||||
|
||||
/**
|
||||
Given a tangent space bump map, computes a new image where the
|
||||
RGB channels are a tangent space normal map and the alpha channel
|
||||
is the original bump map. Assumes the input image is tileable.
|
||||
|
||||
In the resulting image, x = red = tangent, y = green = binormal, and z = blue = normal.
|
||||
|
||||
Particularly useful as part of the idiom:
|
||||
<PRE>
|
||||
GImage normal;
|
||||
computeNormalMap(GImage(filename), normal);
|
||||
return Texture::fromGImage(filename, normal);
|
||||
</PRE>
|
||||
|
||||
*/
|
||||
static void computeNormalMap(
|
||||
const class GImage& bump,
|
||||
class GImage& normal,
|
||||
const BumpMapPreprocess& preprocess = BumpMapPreprocess());
|
||||
|
||||
static void computeNormalMap
|
||||
(int width,
|
||||
int height,
|
||||
int channels,
|
||||
const uint8* src,
|
||||
GImage& normal,
|
||||
const BumpMapPreprocess& preprocess = BumpMapPreprocess());
|
||||
|
||||
/**
|
||||
Bayer demosaicing using the filter proposed in
|
||||
|
||||
HIGH-QUALITY LINEAR INTERPOLATION FOR DEMOSAICING OF BAYER-PATTERNED COLOR IMAGES
|
||||
Henrique S. Malvar, Li-wei He, and Ross Cutler
|
||||
|
||||
The filter wraps at the image boundaries.
|
||||
|
||||
Assumes in != out.
|
||||
*/
|
||||
static void BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
static void BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out);
|
||||
|
||||
/** Fast conversion; the output has 1/2 the size of the input in each direction. Assumes in != out.
|
||||
See G3D::BAYER_G8B8_R8G8_to_R8G8B8_MHC for a much better result. */
|
||||
static void BAYER_G8B8_R8G8_to_Quarter_R8G8B8
|
||||
(int inWidth,
|
||||
int inHeight,
|
||||
const uint8* in,
|
||||
uint8* out);
|
||||
|
||||
/** Attempt to undo fast conversion of G3D::BAYER_G8B8_R8G8_to_Quarter_R8G8B8;
|
||||
the green channel will lose data. Assumes in != out
|
||||
The input should have size 3 * inWidth * inHeight. The output should have size
|
||||
2 * inWidth * 2 * inHeight.
|
||||
*/
|
||||
static void Quarter_R8G8B8_to_BAYER_G8B8_R8G8
|
||||
(int inWidth,
|
||||
int inHeight,
|
||||
const uint8* in,
|
||||
uint8* out);
|
||||
|
||||
/** Overwrites every pixel with one of the two colors in a checkerboard pattern.
|
||||
The fields used from the two colors depend on the current number of channels in @a im.
|
||||
*/
|
||||
static void makeCheckerboard
|
||||
(GImage& im,
|
||||
int checkerSize = 1,
|
||||
const Color4uint8& color1 = Color4uint8(255,255,255,255),
|
||||
const Color4uint8& color2 = Color4uint8(0,0,0,255));
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
113
dep/g3dlite/include/G3D/GLight.h
Normal file
113
dep/g3dlite/include/G3D/GLight.h
Normal file
@@ -0,0 +1,113 @@
|
||||
/**
|
||||
@file GLight.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-11-12
|
||||
@edited 2009-11-08
|
||||
*/
|
||||
|
||||
#ifndef G3D_GLight_h
|
||||
#define G3D_GLight_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Color4.h"
|
||||
|
||||
namespace G3D {
|
||||
class Any;
|
||||
|
||||
/**
|
||||
A light representation that closely follows the OpenGL light format.
|
||||
*/
|
||||
class GLight {
|
||||
public:
|
||||
/** World space position (for a directional light, w = 0 */
|
||||
Vector4 position;
|
||||
|
||||
/** For a spot or directional light, this is the "right vector" that will be used when constructing
|
||||
a reference frame(). */
|
||||
Vector3 rightDirection;
|
||||
|
||||
/** Direction in which the light faces, if a spot light. This is the "look vector" of the light source. */
|
||||
Vector3 spotDirection;
|
||||
|
||||
/** In <B>degrees</B>. 180 = no cutoff (point/dir). Values less than 90 = spot light */
|
||||
float spotCutoff;
|
||||
|
||||
/** If true, G3D::SuperShader will render a cone of light large
|
||||
enough to encompass the entire square that bounds the cutoff
|
||||
angle. This produces a square prism instead of a cone of light
|
||||
when used with a G3D::ShadowMap. for an unshadowed light this
|
||||
has no effect.*/
|
||||
bool spotSquare;
|
||||
|
||||
/** Constant, linear, quadratic */
|
||||
float attenuation[3];
|
||||
|
||||
/** May be outside the range [0, 1] */
|
||||
Color3 color;
|
||||
|
||||
/** If false, this light is ignored */
|
||||
bool enabled;
|
||||
|
||||
/** If false, this light does not create specular highlights
|
||||
(useful when using negative lights). */
|
||||
bool specular;
|
||||
|
||||
/** If false, this light does not create diffuse illumination
|
||||
(useful when rendering a specular-only pass). */
|
||||
bool diffuse;
|
||||
|
||||
GLight();
|
||||
|
||||
/** Accepted forms:
|
||||
- GLight::directional( vector3, color3, [bool, [bool]])
|
||||
- GLight::spot(vector3, vector3, #, color3, [#, [#, [#, [#, [bool, [bool]]]])
|
||||
- GLight::point(vector3, color3, [#, [#, [#, [#, [bool, [bool]]]])
|
||||
- GLight { [all fields] }
|
||||
*/
|
||||
GLight(const Any& any);
|
||||
|
||||
/** Converts the Color3 to an Any. */
|
||||
operator Any() const;
|
||||
|
||||
/** @param toLight will be normalized */
|
||||
static GLight directional(const Vector3& toLight, const Color3& color, bool specular = true, bool diffuse = true);
|
||||
|
||||
static GLight point(const Vector3& pos, const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0.5f, bool specular = true, bool diffuse = true);
|
||||
|
||||
/** @param pointDirection Will be normalized. Points in the
|
||||
direction that light propagates.
|
||||
|
||||
@param cutOffAngleDegrees Must be on the range [0, 90]. This
|
||||
is the angle from the point direction to the edge of the light
|
||||
cone. I.e., a value of 45 produces a light with a 90-degree
|
||||
cone of view.
|
||||
*/
|
||||
static GLight spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees,
|
||||
const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0,
|
||||
bool specular = true, bool diffuse = true);
|
||||
|
||||
/** Creates a spot light that looks at a specific point (by calling spot() ) */
|
||||
static GLight spotTarget(const Vector3& pos, const Vector3& target, float cutOffAngleDegrees,
|
||||
const Color3& color, float constAtt = 1, float linAtt = 0, float quadAtt = 0,
|
||||
bool specular = true, bool diffuse = true) {
|
||||
return spot(pos, target - pos, cutOffAngleDegrees, color, constAtt, linAtt, quadAtt, specular, diffuse);
|
||||
}
|
||||
|
||||
/** Returns the sphere within which this light has some noticable effect. May be infinite.
|
||||
@param cutoff The value at which the light intensity is considered negligible. */
|
||||
class Sphere effectSphere(float cutoff = 30.0f / 255) const;
|
||||
|
||||
/** Computes a reference frame (e.g., for use with G3D::ShadowMap */
|
||||
class CoordinateFrame frame() const;
|
||||
|
||||
bool operator==(const GLight& other) const;
|
||||
bool operator!=(const GLight& other) const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
#endif
|
||||
|
||||
131
dep/g3dlite/include/G3D/GMutex.h
Normal file
131
dep/g3dlite/include/G3D/GMutex.h
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
\file G3D/GMutex.h
|
||||
|
||||
\created 2005-09-22
|
||||
\edited 2013-04-03
|
||||
*/
|
||||
|
||||
#ifndef G3D_GMutex_h
|
||||
#define G3D_GMutex_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef G3D_WINDOWS
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
#if defined(G3D_LINUX) || defined(G3D_OSX)
|
||||
# include <unistd.h> // For usleep
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief A mutual exclusion lock that busy-waits when locking.
|
||||
|
||||
On a machine with one (significant) thread per processor core,
|
||||
a Spinlock may be substantially faster than a mutex.
|
||||
|
||||
\sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32
|
||||
*/
|
||||
class Spinlock {
|
||||
private:
|
||||
|
||||
AtomicInt32 x;
|
||||
|
||||
public:
|
||||
|
||||
inline Spinlock() : x(0) {}
|
||||
|
||||
/** Busy waits until the lock is unlocked, then locks it
|
||||
exclusively. Returns true if the lock succeeded on the first
|
||||
try (indicating no contention).
|
||||
|
||||
Unlike a G3D::GMutex, a single thread cannot re-enter
|
||||
Spinlock::lock() that it already locked.
|
||||
*/
|
||||
inline bool lock() {
|
||||
bool first = true;
|
||||
while (x.compareAndSet(0, 1) == 1) {
|
||||
first = false;
|
||||
# ifdef G3D_WINDOWS
|
||||
Sleep(0);
|
||||
# else
|
||||
usleep(0);
|
||||
# endif
|
||||
}
|
||||
return first;
|
||||
}
|
||||
|
||||
inline void unlock() {
|
||||
x.compareAndSet(1, 0);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Mutual exclusion lock used for synchronization.
|
||||
|
||||
@sa G3D::GThread, G3D::AtomicInt32, G3D::Spinlock
|
||||
*/
|
||||
class GMutex {
|
||||
private:
|
||||
# ifdef G3D_WINDOWS
|
||||
CRITICAL_SECTION m_handle;
|
||||
# else
|
||||
pthread_mutex_t m_handle;
|
||||
pthread_mutexattr_t m_attr;
|
||||
# endif
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GMutex(const GMutex &mlock);
|
||||
GMutex &operator=(const GMutex &);
|
||||
bool operator==(const GMutex&);
|
||||
|
||||
public:
|
||||
GMutex();
|
||||
~GMutex();
|
||||
|
||||
/** Locks the mutex or blocks until available. */
|
||||
void lock();
|
||||
|
||||
/** Locks the mutex if it not already locked.
|
||||
Returns true if lock successful, false otherwise. */
|
||||
bool tryLock();
|
||||
|
||||
/** Unlocks the mutex. */
|
||||
void unlock();
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Automatically locks while in scope.
|
||||
*/
|
||||
class GMutexLock {
|
||||
private:
|
||||
GMutex* m;
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GMutexLock(const GMutexLock &mlock);
|
||||
GMutexLock &operator=(const GMutexLock &);
|
||||
bool operator==(const GMutexLock&);
|
||||
|
||||
public:
|
||||
GMutexLock(GMutex* mutex) {
|
||||
m = mutex;
|
||||
m->lock();
|
||||
}
|
||||
|
||||
~GMutexLock() {
|
||||
m->unlock();
|
||||
}
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
270
dep/g3dlite/include/G3D/GThread.h
Normal file
270
dep/g3dlite/include/G3D/GThread.h
Normal file
@@ -0,0 +1,270 @@
|
||||
/**
|
||||
@file GThread.h
|
||||
|
||||
@created 2005-09-22
|
||||
@edited 2010-09-10
|
||||
|
||||
*/
|
||||
|
||||
#ifndef G3D_GThread_h
|
||||
#define G3D_GThread_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/ThreadSet.h"
|
||||
#include "G3D/Vector2int32.h"
|
||||
#include "G3D/SpawnBehavior.h"
|
||||
#include <string>
|
||||
|
||||
#ifndef G3D_WINDOWS
|
||||
# include <pthread.h>
|
||||
# include <signal.h>
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef shared_ptr<class GThread> GThreadRef;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Platform independent thread implementation. You can either subclass and
|
||||
override GThread::threadMain or call the create method with a method.
|
||||
|
||||
Beware of reference counting and threads. If circular references exist between
|
||||
GThread subclasses then neither class will ever be deallocated. Also,
|
||||
dropping all pointers (and causing deallocation) of a GThread does NOT
|
||||
stop the underlying process.
|
||||
|
||||
\sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32, G3D::ThreadSet
|
||||
*/
|
||||
class GThread : public ReferenceCountedObject {
|
||||
private:
|
||||
// "Status" is a reserved word on FreeBSD
|
||||
enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED};
|
||||
|
||||
// Not implemented on purpose, don't use
|
||||
GThread(const GThread &);
|
||||
GThread& operator=(const GThread&);
|
||||
bool operator==(const GThread&);
|
||||
|
||||
#ifdef G3D_WINDOWS
|
||||
static DWORD WINAPI internalThreadProc(LPVOID param);
|
||||
#else
|
||||
static void* internalThreadProc(void* param);
|
||||
#endif //G3D_WINDOWS
|
||||
|
||||
volatile GStatus m_status;
|
||||
|
||||
// Thread handle to hold HANDLE and pthread_t
|
||||
#ifdef G3D_WINDOWS
|
||||
HANDLE m_handle;
|
||||
HANDLE m_event;
|
||||
#else
|
||||
pthread_t m_handle;
|
||||
#endif //G3D_WINDOWS
|
||||
|
||||
std::string m_name;
|
||||
|
||||
protected:
|
||||
|
||||
/** Overriden by the thread implementor */
|
||||
virtual void threadMain() = 0;
|
||||
|
||||
public:
|
||||
|
||||
/** Returns System::numCores(); put here to break a dependence on System.h */
|
||||
static int numCores();
|
||||
|
||||
typedef shared_ptr<class GThread> Ref;
|
||||
|
||||
GThread(const std::string& name);
|
||||
|
||||
virtual ~GThread();
|
||||
|
||||
/** Constructs a basic GThread without requiring a subclass.
|
||||
|
||||
@param proc The global or static function for the threadMain() */
|
||||
static GThreadRef create(const std::string& name, void (*proc)(void*), void* param = NULL);
|
||||
|
||||
/** Starts the thread and executes threadMain(). Returns false if
|
||||
the thread failed to start (either because it was already started
|
||||
or because the OS refused).
|
||||
|
||||
@param behavior If USE_CURRENT_THREAD, rather than spawning a new thread, this routine
|
||||
runs threadMain on the current thread.
|
||||
*/
|
||||
bool start(SpawnBehavior behavior = USE_NEW_THREAD);
|
||||
|
||||
/** Terminates the thread without notifying or
|
||||
waiting for a cancelation point. */
|
||||
void terminate();
|
||||
|
||||
/**
|
||||
Returns true if threadMain is currently executing. This will
|
||||
only be set when the thread is actually running and might not
|
||||
be set when start() returns. */
|
||||
bool running() const;
|
||||
|
||||
/** True after start() has been called, even through the thread
|
||||
may have already completed(), or be currently running().*/
|
||||
bool started() const;
|
||||
|
||||
/** Returns true if the thread has exited. */
|
||||
bool completed() const;
|
||||
|
||||
/** Waits for the thread to finish executing. */
|
||||
void waitForCompletion();
|
||||
|
||||
/** Returns thread name */
|
||||
const std::string& name() {
|
||||
return m_name;
|
||||
}
|
||||
|
||||
/** For backwards compatibility to G3D 8.xx */
|
||||
static const SpawnBehavior USE_CURRENT_THREAD = G3D::USE_CURRENT_THREAD;
|
||||
/** For backwards compatibility to G3D 8.xx */
|
||||
static const SpawnBehavior USE_NEW_THREAD = G3D::USE_NEW_THREAD;
|
||||
|
||||
enum {
|
||||
/** Tells GThread::runConcurrently() and GThread::runConcurrently2D() to
|
||||
use System::numCores() threads.*/
|
||||
NUM_CORES = -100
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Iterates over a 2D region using multiple threads and
|
||||
blocks until all threads have completed. <p> Evaluates \a
|
||||
object->\a method(\a x, \a y) for every <code>start.x <= x <
|
||||
upTo.x</code> and <code>start.y <= y < upTo.y</code>.
|
||||
Iteration is row major, so each thread can expect to see
|
||||
successive x values. </p>
|
||||
\param maxThreads
|
||||
Maximum number of threads to use. By default at most one
|
||||
thread per processor core will be used.
|
||||
|
||||
Example:
|
||||
|
||||
\code
|
||||
class RayTracer {
|
||||
public:
|
||||
void trace(const Vector2int32& pixel) {
|
||||
...
|
||||
}
|
||||
|
||||
void traceAll() {
|
||||
GThread::runConcurrently2D(Point2int32(0,0), Point2int32(w,h), this, &RayTracer::trace);
|
||||
}
|
||||
};
|
||||
\endcode
|
||||
*/
|
||||
template<class Class>
|
||||
static void runConcurrently2D
|
||||
(const Vector2int32& start,
|
||||
const Vector2int32& upTo,
|
||||
Class* object,
|
||||
void (Class::*method)(int x, int y),
|
||||
int maxThreads = NUM_CORES) {
|
||||
_internal_runConcurrently2DHelper(start, upTo, object, method, static_cast<void (Class::*)(int, int, int)>(NULL), maxThreads);
|
||||
}
|
||||
|
||||
/** Like the other version of runConcurrently2D, but tells the
|
||||
method the thread index that it is running on. That enables
|
||||
the caller to manage per-thread state.
|
||||
*/
|
||||
template<class Class>
|
||||
static void runConcurrently2D
|
||||
(const Vector2int32& start,
|
||||
const Vector2int32& upTo,
|
||||
Class* object,
|
||||
void (Class::*method)(int x, int y, int threadID),
|
||||
int maxThreads = NUM_CORES) {
|
||||
_internal_runConcurrently2DHelper(start, upTo, object, static_cast<void (Class::*)(int, int)>(NULL), method, maxThreads);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// Can't use an inherited class inside of its parent on g++ 4.2.1 if it is later a template parameter
|
||||
|
||||
/** For use by runConcurrently2D. Designed for arbitrary iteration, although only used for
|
||||
interlaced rows in the current implementation. */
|
||||
template<class Class>
|
||||
class _internalGThreadWorker : public GThread {
|
||||
public:
|
||||
/** Start for this thread, which differs from the others */
|
||||
const int threadID;
|
||||
const Vector2int32 start;
|
||||
const Vector2int32 upTo;
|
||||
const Vector2int32 stride;
|
||||
Class* object;
|
||||
void (Class::*method1)(int x, int y);
|
||||
void (Class::*method2)(int x, int y, int threadID);
|
||||
|
||||
_internalGThreadWorker(int threadID,
|
||||
const Vector2int32& start,
|
||||
const Vector2int32& upTo,
|
||||
Class* object,
|
||||
void (Class::*method1)(int x, int y),
|
||||
void (Class::*method2)(int x, int y, int threadID),
|
||||
const Vector2int32& stride) :
|
||||
GThread("runConcurrently2D worker"),
|
||||
threadID(threadID),
|
||||
start(start),
|
||||
upTo(upTo),
|
||||
stride(stride),
|
||||
object(object),
|
||||
method1(method1),
|
||||
method2(method2) {}
|
||||
|
||||
virtual void threadMain() {
|
||||
for (int y = start.y; y < upTo.y; y += stride.y) {
|
||||
// Run whichever method was provided
|
||||
if (method1) {
|
||||
for (int x = start.x; x < upTo.x; x += stride.x) {
|
||||
(object->*method1)(x, y);
|
||||
}
|
||||
} else {
|
||||
for (int x = start.x; x < upTo.x; x += stride.x) {
|
||||
(object->*method2)(x, y, threadID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class Class>
|
||||
void _internal_runConcurrently2DHelper
|
||||
(const Vector2int32& start,
|
||||
const Vector2int32& upTo,
|
||||
Class* object,
|
||||
void (Class::*method1)(int x, int y),
|
||||
void (Class::*method2)(int x, int y, int threadID),
|
||||
int maxThreads) {
|
||||
|
||||
// Create a group of threads
|
||||
if (maxThreads == GThread::NUM_CORES) {
|
||||
maxThreads = GThread::numCores();
|
||||
}
|
||||
|
||||
const int numRows = upTo.y - start.y;
|
||||
const int numThreads = min(maxThreads, numRows);
|
||||
const Vector2int32 stride(1, numThreads);
|
||||
ThreadSet threadSet;
|
||||
for (int t = 0; t < numThreads; ++t) {
|
||||
threadSet.insert(shared_ptr<_internalGThreadWorker<Class> >(new _internalGThreadWorker<Class>(t, start + Vector2int32(0, t), upTo, object, method1, method2, stride)));
|
||||
}
|
||||
|
||||
// Run the threads, reusing the current thread and blocking until
|
||||
// all complete
|
||||
threadSet.start(USE_CURRENT_THREAD);
|
||||
threadSet.waitForCompletion();
|
||||
}
|
||||
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif //G3D_GTHREAD_H
|
||||
90
dep/g3dlite/include/G3D/GUniqueID.h
Normal file
90
dep/g3dlite/include/G3D/GUniqueID.h
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
\file G3D/GUniqueID.h
|
||||
\author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
#ifndef G3D_GUniqueID_h
|
||||
#define G3D_GUniqueID_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Table.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/** Globally unique identifiers. The probability of two different
|
||||
programs generating the same value from UniqueID::create is
|
||||
vanishingly small.
|
||||
|
||||
UniqueIDs optionally contain a 10-bit application specific tag
|
||||
that distinguishes their type.
|
||||
*/
|
||||
class GUniqueID {
|
||||
private:
|
||||
|
||||
uint64 id;
|
||||
|
||||
public:
|
||||
|
||||
/** \sa create */
|
||||
GUniqueID() : id(0) {}
|
||||
|
||||
GUniqueID& operator=(const Any& a);
|
||||
|
||||
/** \sa create */
|
||||
GUniqueID(const Any& a) {
|
||||
*this = a;
|
||||
}
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
/** Returns a 16-character string equivalent to this GUniqueID's uint64 value. */
|
||||
std::string toString16() const;
|
||||
|
||||
static GUniqueID fromString16(const std::string& s);
|
||||
|
||||
/** Returns the ID that has the specified tag (so that it is not uninitialized), but
|
||||
which is a common sentinel "none" value. */
|
||||
static GUniqueID NONE(uint16 tag);
|
||||
|
||||
bool uninitialized() const {
|
||||
return id == 0;
|
||||
}
|
||||
|
||||
uint16 tag() const {
|
||||
return id >> 54;
|
||||
}
|
||||
|
||||
operator uint64() const {
|
||||
return id;
|
||||
}
|
||||
|
||||
bool operator==(const GUniqueID& other) const {
|
||||
return id == other.id;
|
||||
}
|
||||
|
||||
bool operator!=(const GUniqueID& other) const {
|
||||
return id != other.id;
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class TextOutput& t) const;
|
||||
|
||||
void deserialize(class TextInput& t);
|
||||
|
||||
/** Create a new ID */
|
||||
static GUniqueID create(uint16 tag = 0);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
/** For Table and Set */
|
||||
template<> struct HashTrait<class G3D::GUniqueID> {
|
||||
static size_t hashCode(G3D::GUniqueID id) { return (size_t)(G3D::uint64)id; }
|
||||
};
|
||||
|
||||
#endif
|
||||
185
dep/g3dlite/include/G3D/HashTrait.h
Normal file
185
dep/g3dlite/include/G3D/HashTrait.h
Normal file
@@ -0,0 +1,185 @@
|
||||
/**
|
||||
\file G3D/HashTrait.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
\created 2008-10-01
|
||||
\edited 2011-06-09
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_HashTrait_h
|
||||
#define G3D_HashTrait_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Crypto.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/uint128.h"
|
||||
#include <typeinfo>
|
||||
|
||||
#include <stdint.h>
|
||||
#undef get16bits
|
||||
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
|
||||
|| defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
|
||||
#define get16bits(d) (*((const uint16_t *) (d)))
|
||||
#endif
|
||||
|
||||
#if !defined (get16bits)
|
||||
#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)\
|
||||
+(uint32_t)(((const uint8_t *)(d))[0]) )
|
||||
#endif
|
||||
namespace G3D {
|
||||
/** \brief A hash function that is faster than CRC32 for arbitrary long strings
|
||||
\cite From http://www.azillionmonkeys.com/qed/hash.html by Paul Hsieh*/
|
||||
inline uint32_t superFastHash (const void* _data, size_t numBytes) {
|
||||
const char* data = (const char*)_data;
|
||||
uint32_t hash = (uint32_t)numBytes;
|
||||
uint32_t tmp;
|
||||
int rem;
|
||||
|
||||
if ((numBytes <= 0) || (data == NULL)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
rem = numBytes & 3;
|
||||
numBytes >>= 2;
|
||||
|
||||
/* Main loop */
|
||||
for (;numBytes > 0; --numBytes) {
|
||||
hash += get16bits (data);
|
||||
tmp = (get16bits (data+2) << 11) ^ hash;
|
||||
hash = (hash << 16) ^ tmp;
|
||||
data += 2*sizeof (uint16_t);
|
||||
hash += hash >> 11;
|
||||
}
|
||||
|
||||
/* Handle end cases */
|
||||
switch (rem) {
|
||||
case 3: hash += get16bits (data);
|
||||
hash ^= hash << 16;
|
||||
hash ^= data[sizeof (uint16_t)] << 18;
|
||||
hash += hash >> 11;
|
||||
break;
|
||||
case 2: hash += get16bits (data);
|
||||
hash ^= hash << 11;
|
||||
hash += hash >> 17;
|
||||
break;
|
||||
case 1: hash += *data;
|
||||
hash ^= hash << 10;
|
||||
hash += hash >> 1;
|
||||
}
|
||||
|
||||
/* Force "avalanching" of final 127 bits */
|
||||
hash ^= hash << 3;
|
||||
hash += hash >> 5;
|
||||
hash ^= hash << 4;
|
||||
hash += hash >> 17;
|
||||
hash ^= hash << 25;
|
||||
hash += hash >> 6;
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Thomas Wang's 64-to-32-bit mix hash based on Robert Jenkin's hash http://www.concentric.net/~ttwang/tech/inthash.htm
|
||||
|
||||
Found by Morgan to produce the best net performance for building tables from Vector4int16
|
||||
*/
|
||||
inline uint32_t wangHash6432Shift(int64 key) {
|
||||
key = (~key) + (key << 18); // key = (key << 18) - key - 1;
|
||||
key = key ^ (key >> 31);
|
||||
key = key * 21; // key = (key + (key << 2)) + (key << 4);
|
||||
key = key ^ (key >> 11);
|
||||
key = key + (key << 6);
|
||||
return uint32_t(key) ^ uint32_t(key >> 22);
|
||||
}
|
||||
|
||||
}
|
||||
#undef get16bits
|
||||
|
||||
/** Must be specialized for custom types.
|
||||
@see G3D::Table for specialization requirements.
|
||||
*/
|
||||
template <typename T> struct HashTrait{};
|
||||
|
||||
template <typename T> struct HashTrait<T*> {
|
||||
static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k) >> 1; }
|
||||
};
|
||||
|
||||
/** For use with \code Table<std::type_info* const, ValueType> \endcode. */
|
||||
template <> struct HashTrait <std::type_info* const> {
|
||||
static size_t hashCode(const std::type_info* const t) {
|
||||
# ifdef _MSC_VER
|
||||
return t->hash_code();
|
||||
# else
|
||||
return reinterpret_cast<size_t>(t) >> 1;
|
||||
# endif
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::int16> {
|
||||
static size_t hashCode(G3D::int16 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::uint16> {
|
||||
static size_t hashCode(G3D::uint16 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::int32> {
|
||||
static size_t hashCode(G3D::int32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::uint32> {
|
||||
static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
|
||||
#ifdef G3D_OSX
|
||||
template <> struct HashTrait <long unsigned int> {
|
||||
static size_t hashCode(G3D::uint32 k) { return static_cast<size_t>(k); }
|
||||
};
|
||||
#endif
|
||||
|
||||
|
||||
template <> struct HashTrait <G3D::uint64> {
|
||||
static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k) ^ static_cast<size_t>(k >> 32); }
|
||||
};
|
||||
|
||||
template <> struct HashTrait <G3D::int64> {
|
||||
static size_t hashCode(G3D::int64 k) { return HashTrait<G3D::uint64>::hashCode(G3D::uint64(k)); }
|
||||
};
|
||||
|
||||
|
||||
template <> struct HashTrait <std::string> {
|
||||
static size_t hashCode(const std::string& k) {
|
||||
return G3D::superFastHash(k.c_str(), k.size());
|
||||
//return static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size()));
|
||||
}
|
||||
};
|
||||
|
||||
template <> struct HashTrait<G3D::uint128> {
|
||||
static size_t hashCode(G3D::uint128 key) {
|
||||
return G3D::superFastHash(&key, sizeof(key));
|
||||
//return HashTrait<G3D::uint64>::hashCode(key.hi) ^ HashTrait<G3D::uint64>::hashCode(key.lo);
|
||||
|
||||
#if 0 // Really slow under gcc
|
||||
// Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
|
||||
static const G3D::uint128 FNV_PRIME_128(1 << 24, 0x159);
|
||||
static const G3D::uint128 FNV_OFFSET_128(0xCF470AAC6CB293D2ULL, 0xF52F88BF32307F8FULL);
|
||||
|
||||
G3D::uint128 hash = FNV_OFFSET_128;
|
||||
G3D::uint128 mask(0, 0xFF);
|
||||
for (int i = 0; i < 16; ++i) {
|
||||
hash *= FNV_PRIME_128;
|
||||
hash ^= (mask & key);
|
||||
key >>= 8;
|
||||
}
|
||||
|
||||
G3D::uint64 foldedHash = hash.hi ^ hash.lo;
|
||||
return static_cast<size_t>((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF));
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
83
dep/g3dlite/include/G3D/Image1.h
Normal file
83
dep/g3dlite/include/G3D/Image1.h
Normal file
@@ -0,0 +1,83 @@
|
||||
/**
|
||||
\file G3D/Image1.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2007-01-31
|
||||
\edited 2011-08-31
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_Image1_h
|
||||
#define G3D_Image1_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color1.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef shared_ptr<class Image1> Image1Ref;
|
||||
|
||||
/**
|
||||
Luminance image with 32-bit floating point storage.
|
||||
|
||||
See also G3D::Image1unorm8, G3D::GImage.
|
||||
*/
|
||||
class Image1 : public Map2D<Color1, Color1> {
|
||||
public:
|
||||
|
||||
typedef Image1 Type;
|
||||
typedef shared_ptr<class Image1> Ref;
|
||||
typedef Color1 Storage;
|
||||
typedef Color1 Compute;
|
||||
|
||||
protected:
|
||||
|
||||
Image1(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1unorm8* src, int w, int h);
|
||||
void copyArray(const Color3unorm8* src, int w, int h);
|
||||
void copyArray(const Color4unorm8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage1unorm8(const shared_ptr<class Image1unorm8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::Image.
|
||||
|
||||
If there is an alpha channel on the input, it is stripped.
|
||||
Values are automatically scaled to the range [0, 1]. */
|
||||
void load(const std::string& filename);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::Image.
|
||||
|
||||
The data values are assumed to be on the range [0, 1] and will
|
||||
be scaled appropriately for the save format.*/
|
||||
void save(const std::string& filename);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
80
dep/g3dlite/include/G3D/Image1uint8.h
Normal file
80
dep/g3dlite/include/G3D/Image1uint8.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
@file Image1uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE1UINT8_H
|
||||
#define G3D_IMAGE1UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color1uint8.h"
|
||||
#include "G3D/Color1.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image1uint8> Image1uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for luminance 8-bit images.
|
||||
|
||||
See also G3D::Image3, G3D::GImage
|
||||
*/
|
||||
class Image1uint8 : public Map2D<Color1uint8, Color1> {
|
||||
public:
|
||||
|
||||
typedef Image1uint8 Type;
|
||||
typedef Image1uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image1uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage1(const ReferenceCountedPointer<class Image1>& im);
|
||||
static Ref fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
75
dep/g3dlite/include/G3D/Image3.h
Normal file
75
dep/g3dlite/include/G3D/Image3.h
Normal file
@@ -0,0 +1,75 @@
|
||||
/**
|
||||
\file G3D/Image3.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2007-01-31
|
||||
\edited 2011-08-31
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_IMAGE3_H
|
||||
#define G3D_IMAGE3_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef shared_ptr<class Image3> Image3Ref;
|
||||
|
||||
/**
|
||||
RGB image with 32-bit floating point storage for each channel.
|
||||
|
||||
See also G3D::Image3unorm8, G3D::GImage.
|
||||
*/
|
||||
class Image3 : public Map2D<Color3, Color3> {
|
||||
public:
|
||||
|
||||
typedef Image3 Type;
|
||||
typedef shared_ptr<class Image3> Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image3(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1unorm8* src, int w, int h);
|
||||
void copyArray(const Color3unorm8* src, int w, int h);
|
||||
void copyArray(const Color4unorm8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage3unorm8(const shared_ptr<class Image3unorm8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. Converts 8-bit formats to the range (0, 1) */
|
||||
void load(const std::string& filename);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. Assumes the data is on the range (0, 1) if saving to an 8-bit format.*/
|
||||
void save(const std::string& filename);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
85
dep/g3dlite/include/G3D/Image3uint8.h
Normal file
85
dep/g3dlite/include/G3D/Image3uint8.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
@file Image3uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE3UINT8_H
|
||||
#define G3D_IMAGE3UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color3uint8.h"
|
||||
#include "G3D/Color3.h"
|
||||
#include "G3D/GImage.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image3uint8> Image3uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for RGB 8-bit per channel images.
|
||||
|
||||
See also G3D::Image3, G3D::GImage
|
||||
*/
|
||||
class Image3uint8 : public Map2D<Color3uint8, Color3> {
|
||||
public:
|
||||
|
||||
typedef Image3uint8 Type;
|
||||
typedef Image3uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image3uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage3(const ReferenceCountedPointer<class Image3>& im);
|
||||
static Ref fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Extracts color channel 0 <= c <= 2 and returns it as a new monochrome image. */
|
||||
ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
80
dep/g3dlite/include/G3D/Image4.h
Normal file
80
dep/g3dlite/include/G3D/Image4.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/**
|
||||
\file G3D/Image4.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2007-01-31
|
||||
\edited 2011-08-11
|
||||
*/
|
||||
|
||||
|
||||
#ifndef G3D_Image4_h
|
||||
#define G3D_Image4_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color4.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef shared_ptr<class Image4> Image4Ref;
|
||||
|
||||
/**
|
||||
RGBA image with 32-bit floating point storage for each channel.
|
||||
|
||||
Whenever a method needs to convert from RGB to RGBA, A=1 is assumed.
|
||||
|
||||
Bilinear interpolation on Image4 is about 8x faster than on
|
||||
Image4unorm8 due to the large cost of converting int->float on modern
|
||||
machines.
|
||||
|
||||
@sa G3D::Image4unorm8, G3D::GImage.
|
||||
*/
|
||||
class Image4 : public Map2D<Color4, Color4> {
|
||||
public:
|
||||
|
||||
typedef Image4 Type;
|
||||
typedef shared_ptr<class Image4> Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image4(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1unorm8* src, int w, int h);
|
||||
void copyArray(const Color3unorm8* src, int w, int h);
|
||||
void copyArray(const Color4unorm8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4unorm8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage4unorm8(const shared_ptr<class Image4unorm8>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. */
|
||||
void load(const std::string& filename);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename);
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
85
dep/g3dlite/include/G3D/Image4uint8.h
Normal file
85
dep/g3dlite/include/G3D/Image4uint8.h
Normal file
@@ -0,0 +1,85 @@
|
||||
/**
|
||||
@file Image4uint8.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2007-01-31
|
||||
@edited 2007-01-31
|
||||
*/
|
||||
|
||||
#ifndef G3D_IMAGE4UINT8_H
|
||||
#define G3D_IMAGE4UINT8_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Map2D.h"
|
||||
#include "G3D/Color4uint8.h"
|
||||
#include "G3D/Color4.h"
|
||||
#include "G3D/GImage.h"
|
||||
#include "G3D/Image1uint8.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
typedef ReferenceCountedPointer<class Image4uint8> Image4uint8Ref;
|
||||
|
||||
/**
|
||||
Compact storage for RGBA 8-bit per channel images.
|
||||
|
||||
See also G3D::Image4, G3D::GImage
|
||||
*/
|
||||
class Image4uint8 : public Map2D<Color4uint8, Color4> {
|
||||
public:
|
||||
|
||||
typedef Image4uint8 Type;
|
||||
typedef Image4uint8Ref Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Image4uint8(int w, int h, WrapMode wrap);
|
||||
|
||||
void copyGImage(const class GImage& im);
|
||||
void copyArray(const Color1* src, int w, int h);
|
||||
void copyArray(const Color3* src, int w, int h);
|
||||
void copyArray(const Color4* src, int w, int h);
|
||||
void copyArray(const Color1uint8* src, int w, int h);
|
||||
void copyArray(const Color3uint8* src, int w, int h);
|
||||
void copyArray(const Color4uint8* src, int w, int h);
|
||||
|
||||
public:
|
||||
|
||||
const class ImageFormat* format() const;
|
||||
|
||||
/** Creates an all-zero width x height image. */
|
||||
static Ref createEmpty(int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
/** Creates a 0 x 0 image. */
|
||||
static Ref createEmpty(WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
|
||||
static Ref fromFile(const std::string& filename, WrapMode wrap = WrapMode::ERROR, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromArray(const class Color1uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4uint8* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color1* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color3* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
static Ref fromArray(const class Color4* ptr, int width, int height, WrapMode wrap = WrapMode::ERROR);
|
||||
|
||||
static Ref fromImage4(const ReferenceCountedPointer<class Image4>& im);
|
||||
|
||||
/** Loads from any of the file formats supported by G3D::GImage. If there is an alpha channel on the input,
|
||||
it is stripped. */
|
||||
void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Saves in any of the formats supported by G3D::GImage. */
|
||||
void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
|
||||
|
||||
/** Extracts color channel 0 <= c <= 3 and returns it as a new monochrome image. */
|
||||
ReferenceCountedPointer<class Image1uint8> getChannel(int c) const;
|
||||
};
|
||||
|
||||
} // G3D
|
||||
|
||||
#endif
|
||||
567
dep/g3dlite/include/G3D/ImageFormat.h
Normal file
567
dep/g3dlite/include/G3D/ImageFormat.h
Normal file
@@ -0,0 +1,567 @@
|
||||
/**
|
||||
\file G3D/ImageFormat.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2003-05-23
|
||||
\edited 2013-06-06
|
||||
*/
|
||||
|
||||
#ifndef GLG3D_ImageFormat_h
|
||||
#define GLG3D_ImageFormat_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/enumclass.h"
|
||||
#include "G3D/Any.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Information about common image formats. Don't construct these;
|
||||
use the methods provided to access the const instances.
|
||||
|
||||
For most formats, the number indicates the number of bits per
|
||||
channel and a suffix of "F" indicates floating point (following
|
||||
OpenGL conventions). This does not hold for the YUV and DXT
|
||||
formats.
|
||||
|
||||
\sa G3D::Image, G3D::Texture, G3D::ImageConvert
|
||||
*/
|
||||
class ImageFormat {
|
||||
public:
|
||||
|
||||
// Must update ImageFormat::name() when this enum changes.
|
||||
enum Code {
|
||||
CODE_AUTO = -2,
|
||||
CODE_NONE = -1,
|
||||
CODE_L8,
|
||||
CODE_L16,
|
||||
CODE_L16F,
|
||||
CODE_L32F,
|
||||
|
||||
CODE_A8,
|
||||
CODE_A16,
|
||||
CODE_A16F,
|
||||
CODE_A32F,
|
||||
|
||||
CODE_LA4,
|
||||
CODE_LA8,
|
||||
CODE_LA16,
|
||||
CODE_LA16F,
|
||||
CODE_LA32F,
|
||||
|
||||
CODE_RGB5,
|
||||
CODE_RGB5A1,
|
||||
CODE_RGB8,
|
||||
CODE_RGB10,
|
||||
CODE_RGB10A2,
|
||||
CODE_RGB16,
|
||||
CODE_RGB16F,
|
||||
CODE_RGB32F,
|
||||
CODE_R11G11B10F,
|
||||
CODE_RGB9E5F,
|
||||
|
||||
CODE_RGB8I,
|
||||
CODE_RGB8UI,
|
||||
|
||||
CODE_RGBA8I,
|
||||
CODE_RGBA8UI,
|
||||
|
||||
CODE_RGB8_SNORM,
|
||||
CODE_RGBA8_SNORM,
|
||||
CODE_RGB16_SNORM,
|
||||
CODE_RGBA16_SNORM,
|
||||
|
||||
CODE_ARGB8,
|
||||
CODE_BGR8,
|
||||
CODE_BGRA8,
|
||||
|
||||
CODE_R8,
|
||||
CODE_R8I,
|
||||
CODE_R8UI,
|
||||
|
||||
CODE_R16,
|
||||
CODE_R16I,
|
||||
CODE_R16UI,
|
||||
|
||||
CODE_R32I,
|
||||
CODE_R32UI,
|
||||
|
||||
CODE_RG8,
|
||||
CODE_RG8I,
|
||||
CODE_RG8UI,
|
||||
|
||||
CODE_RG16,
|
||||
CODE_RG16I,
|
||||
CODE_RG16UI,
|
||||
|
||||
CODE_R16F,
|
||||
CODE_RG16F,
|
||||
|
||||
CODE_RG32I,
|
||||
CODE_RG32UI,
|
||||
|
||||
CODE_R32F,
|
||||
CODE_RG32F,
|
||||
|
||||
CODE_RGBA8,
|
||||
CODE_RGBA16,
|
||||
CODE_RGBA16F,
|
||||
CODE_RGBA32F,
|
||||
|
||||
CODE_RGBA16I,
|
||||
CODE_RGBA16UI,
|
||||
|
||||
CODE_RGB32I,
|
||||
CODE_RGB32UI,
|
||||
CODE_RGBA32I,
|
||||
CODE_RGBA32UI,
|
||||
|
||||
CODE_BAYER_RGGB8,
|
||||
CODE_BAYER_GRBG8,
|
||||
CODE_BAYER_GBRG8,
|
||||
CODE_BAYER_BGGR8,
|
||||
CODE_BAYER_RGGB32F,
|
||||
CODE_BAYER_GRBG32F,
|
||||
CODE_BAYER_GBRG32F,
|
||||
CODE_BAYER_BGGR32F,
|
||||
|
||||
CODE_HSV8,
|
||||
CODE_HSV32F,
|
||||
|
||||
CODE_YUV420_PLANAR,
|
||||
CODE_YUV422,
|
||||
CODE_YUV444,
|
||||
|
||||
CODE_RGB_DXT1,
|
||||
CODE_RGBA_DXT1,
|
||||
CODE_RGBA_DXT3,
|
||||
CODE_RGBA_DXT5,
|
||||
|
||||
CODE_SRGB8,
|
||||
CODE_SRGBA8,
|
||||
|
||||
CODE_SL8,
|
||||
CODE_SLA8,
|
||||
|
||||
CODE_SRGB_DXT1,
|
||||
CODE_SRGBA_DXT1,
|
||||
CODE_SRGBA_DXT3,
|
||||
CODE_SRGBA_DXT5,
|
||||
|
||||
CODE_DEPTH16,
|
||||
CODE_DEPTH24,
|
||||
CODE_DEPTH32,
|
||||
CODE_DEPTH32F,
|
||||
|
||||
CODE_STENCIL1,
|
||||
CODE_STENCIL4,
|
||||
CODE_STENCIL8,
|
||||
CODE_STENCIL16,
|
||||
|
||||
CODE_DEPTH24_STENCIL8,
|
||||
|
||||
CODE_NUM
|
||||
};
|
||||
|
||||
enum ColorSpace {
|
||||
COLOR_SPACE_NONE,
|
||||
COLOR_SPACE_RGB,
|
||||
COLOR_SPACE_HSV,
|
||||
COLOR_SPACE_YUV,
|
||||
COLOR_SPACE_SRGB
|
||||
};
|
||||
|
||||
enum BayerPattern {
|
||||
BAYER_PATTERN_NONE,
|
||||
BAYER_PATTERN_RGGB,
|
||||
BAYER_PATTERN_GRBG,
|
||||
BAYER_PATTERN_GBRG,
|
||||
BAYER_PATTERN_BGGR
|
||||
};
|
||||
|
||||
|
||||
enum NumberFormat {
|
||||
FLOATING_POINT_FORMAT,
|
||||
INTEGER_FORMAT,
|
||||
NORMALIZED_FIXED_POINT_FORMAT,
|
||||
OTHER // e.g. DXT
|
||||
};
|
||||
|
||||
/** Number of channels (1 for a depth texture). */
|
||||
int numComponents;
|
||||
bool compressed;
|
||||
|
||||
/** Useful for serializing. */
|
||||
Code code;
|
||||
|
||||
ColorSpace colorSpace;
|
||||
|
||||
/** If this is a Bayer format, what is the pattern. */
|
||||
BayerPattern bayerPattern;
|
||||
|
||||
/** The OpenGL format equivalent to this one, e.g, GL_RGB8 Zero if there is no equivalent. This is actually a GLenum */
|
||||
int openGLFormat;
|
||||
|
||||
/** The OpenGL base format equivalent to this one (e.g., GL_RGB, GL_ALPHA). Zero if there is no equivalent. */
|
||||
int openGLBaseFormat;
|
||||
|
||||
int luminanceBits;
|
||||
|
||||
/** Number of bits per pixel storage for alpha values; Zero for compressed textures and non-RGB. */
|
||||
int alphaBits;
|
||||
|
||||
/** Number of bits per pixel storage for red values; Zero for compressed textures and non-RGB. */
|
||||
int redBits;
|
||||
|
||||
/** Number of bits per pixel storage for green values; Zero for compressed textures and non-RGB. */
|
||||
int greenBits;
|
||||
|
||||
/** Number of bits per pixel storage for blue values; Zero for compressed textures and non-RGB. */
|
||||
int blueBits;
|
||||
|
||||
/** Number of bits per pixel */
|
||||
int stencilBits;
|
||||
|
||||
/** Number of depth bits (for depth textures; e.g. shadow maps) */
|
||||
int depthBits;
|
||||
|
||||
/** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */
|
||||
int cpuBitsPerPixel;
|
||||
|
||||
/**
|
||||
Amount of GPU memory per pixel on most graphics cards, for formats supported by OpenGL. This is
|
||||
only an estimate--the actual amount of memory may be different on your actual card.
|
||||
|
||||
This may be greater than the sum of the per-channel bits
|
||||
because graphics cards need to pad to the nearest 1, 2, or
|
||||
4 bytes.
|
||||
*/
|
||||
int openGLBitsPerPixel;
|
||||
|
||||
/** The OpenGL bytes (type) format of the data buffer used with this texture format, e.g., GL_UNSIGNED_BYTE */
|
||||
int openGLDataFormat;
|
||||
|
||||
/** True if there is no alpha channel for this texture. */
|
||||
bool opaque;
|
||||
|
||||
|
||||
/** True if the bit depths specified are for float formats. TODO: Remove, replace with function keying off numberFormat */
|
||||
bool floatingPoint;
|
||||
|
||||
/** Indicates whether this format treats numbers as integers, floating point, or normalized fixed point */
|
||||
NumberFormat numberFormat;
|
||||
|
||||
/** Human readable name of this format.*/
|
||||
const std::string& name() const;
|
||||
|
||||
/** True if data in otherFormat is binary compatible */
|
||||
bool canInterpretAs(const ImageFormat* otherFormat) const;
|
||||
|
||||
/** Returns ImageFormat representing the same channels as \a
|
||||
otherFormat plus an alpha channel, all with at least the same
|
||||
precision as \a otherFormat, or returns NULL if an equivalent
|
||||
format is unavailable. Will return itself if already contains
|
||||
an alpha channel. */
|
||||
static const ImageFormat* getFormatWithAlpha(const ImageFormat* otherFormat);
|
||||
|
||||
static const ImageFormat* getSRGBFormat(const ImageFormat* otherFormat);
|
||||
|
||||
/** Takes the same values that name() returns */
|
||||
static const ImageFormat* fromString(const std::string& s);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ImageFormat
|
||||
(int numComponents,
|
||||
bool compressed,
|
||||
int glFormat,
|
||||
int glBaseFormat,
|
||||
int luminanceBits,
|
||||
int alphaBits,
|
||||
int redBits,
|
||||
int greenBits,
|
||||
int blueBits,
|
||||
int depthBits,
|
||||
int stencilBits,
|
||||
int openGLBitsPerPixel,
|
||||
int cpuBitsPerPixel,
|
||||
int glDataFormat,
|
||||
bool opaque,
|
||||
NumberFormat numberFormat,
|
||||
Code code,
|
||||
ColorSpace colorSpace,
|
||||
BayerPattern bayerPattern = BAYER_PATTERN_NONE);
|
||||
|
||||
public:
|
||||
|
||||
static const ImageFormat* L8();
|
||||
|
||||
static const ImageFormat* L16();
|
||||
|
||||
static const ImageFormat* L16F();
|
||||
|
||||
static const ImageFormat* L32F();
|
||||
|
||||
static const ImageFormat* A8();
|
||||
|
||||
static const ImageFormat* A16();
|
||||
|
||||
static const ImageFormat* A16F();
|
||||
|
||||
static const ImageFormat* A32F();
|
||||
|
||||
static const ImageFormat* LA4();
|
||||
|
||||
static const ImageFormat* LA8();
|
||||
|
||||
static const ImageFormat* LA16();
|
||||
|
||||
static const ImageFormat* LA16F();
|
||||
|
||||
static const ImageFormat* LA32F();
|
||||
|
||||
static const ImageFormat* BGR8();
|
||||
|
||||
static const ImageFormat* BGRA8();
|
||||
|
||||
static const ImageFormat* R8();
|
||||
static const ImageFormat* R8I();
|
||||
static const ImageFormat* R8UI();
|
||||
|
||||
static const ImageFormat* R16();
|
||||
static const ImageFormat* R16I();
|
||||
static const ImageFormat* R16UI();
|
||||
|
||||
static const ImageFormat* R32I();
|
||||
static const ImageFormat* R32UI();
|
||||
|
||||
static const ImageFormat* RG8();
|
||||
static const ImageFormat* RG8I();
|
||||
static const ImageFormat* RG8UI();
|
||||
|
||||
static const ImageFormat* RG16();
|
||||
static const ImageFormat* RG16I();
|
||||
static const ImageFormat* RG16UI();
|
||||
|
||||
static const ImageFormat* R16F();
|
||||
static const ImageFormat* RG16F();
|
||||
|
||||
static const ImageFormat* RG32I();
|
||||
static const ImageFormat* RG32UI();
|
||||
|
||||
static const ImageFormat* R32F();
|
||||
static const ImageFormat* RG32F();
|
||||
|
||||
static const ImageFormat* RGB5();
|
||||
|
||||
static const ImageFormat* RGB5A1();
|
||||
|
||||
static const ImageFormat* RGB8();
|
||||
|
||||
static const ImageFormat* RGB10();
|
||||
|
||||
static const ImageFormat* RGB10A2();
|
||||
|
||||
static const ImageFormat* RGB16();
|
||||
|
||||
static const ImageFormat* RGB16F();
|
||||
|
||||
static const ImageFormat* RGB32F();
|
||||
|
||||
static const ImageFormat* RGBA8();
|
||||
|
||||
static const ImageFormat* RGBA16();
|
||||
|
||||
static const ImageFormat* RGBA16F();
|
||||
|
||||
static const ImageFormat* RGBA32F();
|
||||
|
||||
static const ImageFormat* RGBA16I();
|
||||
static const ImageFormat* RGBA16UI();
|
||||
|
||||
static const ImageFormat* RGB32UI();
|
||||
static const ImageFormat* RGB32I();
|
||||
static const ImageFormat* RGBA32I();
|
||||
static const ImageFormat* RGBA32UI();
|
||||
|
||||
static const ImageFormat* R11G11B10F();
|
||||
|
||||
static const ImageFormat* RGB9E5F();
|
||||
|
||||
static const ImageFormat* RGB8I();
|
||||
|
||||
static const ImageFormat* RGB8UI();
|
||||
|
||||
static const ImageFormat* RGBA8I();
|
||||
|
||||
static const ImageFormat* RGBA8UI();
|
||||
|
||||
static const ImageFormat* RGB8_SNORM();
|
||||
static const ImageFormat* RGBA8_SNORM();
|
||||
static const ImageFormat* RGB16_SNORM();
|
||||
static const ImageFormat* RGBA16_SNORM();
|
||||
|
||||
static const ImageFormat* RGB_DXT1();
|
||||
|
||||
static const ImageFormat* RGBA_DXT1();
|
||||
|
||||
static const ImageFormat* RGBA_DXT3();
|
||||
|
||||
static const ImageFormat* RGBA_DXT5();
|
||||
|
||||
static const ImageFormat* SRGB8();
|
||||
|
||||
static const ImageFormat* SRGBA8();
|
||||
|
||||
static const ImageFormat* SL8();
|
||||
|
||||
static const ImageFormat* SLA8();
|
||||
|
||||
static const ImageFormat* SRGB_DXT1();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT1();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT3();
|
||||
|
||||
static const ImageFormat* SRGBA_DXT5();
|
||||
|
||||
static const ImageFormat* DEPTH16();
|
||||
|
||||
static const ImageFormat* DEPTH24();
|
||||
|
||||
static const ImageFormat* DEPTH32();
|
||||
|
||||
static const ImageFormat* DEPTH32F();
|
||||
|
||||
static const ImageFormat* STENCIL1();
|
||||
|
||||
static const ImageFormat* STENCIL4();
|
||||
|
||||
static const ImageFormat* STENCIL8();
|
||||
|
||||
static const ImageFormat* STENCIL16();
|
||||
|
||||
static const ImageFormat* DEPTH24_STENCIL8();
|
||||
|
||||
static const ImageFormat* YUV420_PLANAR();
|
||||
|
||||
static const ImageFormat* YUV422();
|
||||
|
||||
static const ImageFormat* YUV444();
|
||||
|
||||
/**
|
||||
NULL pointer; indicates that the G3D::Texture class should choose
|
||||
either RGBA8 or RGB8 depending on the presence of an alpha channel
|
||||
in the input.
|
||||
*/
|
||||
static const ImageFormat* AUTO() { return NULL; }
|
||||
|
||||
/** Returns DEPTH16, DEPTH24, or DEPTH32 according to the bits
|
||||
specified. You can use "glGetInteger(GL_DEPTH_BITS)" to match
|
||||
the screen's format.*/
|
||||
static const ImageFormat* depth(int depthBits = 24);
|
||||
|
||||
/** Returns STENCIL1, STENCIL4, STENCIL8 or STENCIL16 according to the bits
|
||||
specified. You can use "glGetInteger(GL_STENCIL_BITS)" to match
|
||||
the screen's format.*/
|
||||
static const ImageFormat* stencil(int bits = 8);
|
||||
|
||||
/** Returns the matching ImageFormat* identified by the Code. May return NULL
|
||||
if this format's code is reserved but not yet implemented by G3D. */
|
||||
static const ImageFormat* fromCode(ImageFormat::Code code);
|
||||
|
||||
|
||||
/** For use with ImageFormat::convert. */
|
||||
class BayerAlgorithm {
|
||||
public:
|
||||
enum Value {
|
||||
NEAREST,
|
||||
BILINEAR,
|
||||
MHC,
|
||||
BEST = MHC
|
||||
};
|
||||
private:
|
||||
static const char* toString(int i, Value& v) {
|
||||
static const char* str[] = {"NEAREST", "BILINEAR", "MHC", "BEST", NULL};
|
||||
static const Value val[] = {NEAREST, BILINEAR, MHC, BEST};
|
||||
const char* s = str[i];
|
||||
if (s) {
|
||||
v = val[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
Value value;
|
||||
|
||||
public:
|
||||
|
||||
G3D_DECLARE_ENUM_CLASS_METHODS(BayerAlgorithm);
|
||||
};
|
||||
|
||||
/** Converts between arbitrary formats on the CPU. Not all format conversions are supported or directly supported.
|
||||
Formats without direct conversions will attempt to convert through RGBA first.
|
||||
|
||||
A conversion routine might only support source or destination padding or y inversion or none.
|
||||
If support is needed and not available in any of the direct conversion routines, then no conversion is done.
|
||||
|
||||
YUV422 expects data in YUY2 format (Y, U, Y2, v). Most YUV formats require width and heights that are multiples of 2.
|
||||
|
||||
Returns true if a conversion was available, false if none occurred.
|
||||
|
||||
\deprecated
|
||||
\sa G3D::ImageConvert
|
||||
*/
|
||||
static bool convert(const Array<const void*>& srcBytes, int srcWidth, int srcHeight, const ImageFormat* srcFormat, int srcRowPadBits,
|
||||
const Array<void*>& dstBytes, const ImageFormat* dstFormat, int dstRowPadBits,
|
||||
bool invertY = false, BayerAlgorithm bayerAlg = BayerAlgorithm::MHC);
|
||||
|
||||
/**
|
||||
Checks if a conversion between two formats is available.
|
||||
\deprecated
|
||||
\sa G3D::ImageConvert
|
||||
*/
|
||||
static bool conversionAvailable(const ImageFormat* srcFormat, int srcRowPadBits, const ImageFormat* dstFormat, int dstRowPadBits, bool invertY = false);
|
||||
|
||||
/** Does this contain exactly one unorm8 component? */
|
||||
bool representableAsColor1unorm8() const;
|
||||
|
||||
/** Does this contain exactly two unorm8 components? */
|
||||
bool representableAsColor2unorm8() const;
|
||||
|
||||
/** Does this contain exactly three unorm8 components? */
|
||||
bool representableAsColor3unorm8() const;
|
||||
|
||||
/** Does this contain exactly four unorm8 components? */
|
||||
bool representableAsColor4unorm8() const;
|
||||
|
||||
/** Returns a Color4 that masks off unused components in the format, given in RGBA
|
||||
For example, the mask for R32F is (1,0,0,0), for A32F is (0,0,0,1), for RGB32F is (1,1,1,0).
|
||||
(Note that luminance is interpreted as using only the R channel, even though RGB would make more sense
|
||||
to me...)
|
||||
*/
|
||||
Color4 channelMask() const;
|
||||
|
||||
bool isIntegerFormat() const{
|
||||
return (numberFormat == INTEGER_FORMAT);
|
||||
}
|
||||
|
||||
/** Returns true if these formats have the same components
|
||||
(possibly in different NumberFormat%s or sizes) */
|
||||
bool sameComponents(const ImageFormat* other) const;
|
||||
|
||||
};
|
||||
|
||||
typedef ImageFormat TextureFormat;
|
||||
|
||||
}
|
||||
|
||||
template <>
|
||||
struct HashTrait<const G3D::ImageFormat*> {
|
||||
static size_t hashCode(const G3D::ImageFormat* key) { return reinterpret_cast<size_t>(key); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
55
dep/g3dlite/include/G3D/Intersect.h
Normal file
55
dep/g3dlite/include/G3D/Intersect.h
Normal file
@@ -0,0 +1,55 @@
|
||||
/**
|
||||
@file Intersect.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-06-29
|
||||
@edited 2009-06-29
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
|
||||
From the G3D Innovation Engine
|
||||
http://g3d.sf.net
|
||||
*/
|
||||
#ifndef G3D_Intersect
|
||||
#define G3D_Intersect
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Ray.h"
|
||||
#include "G3D/AABox.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
@beta
|
||||
*/
|
||||
class Intersect {
|
||||
public:
|
||||
|
||||
/** \brief Returns true if the intersection of the ray and the solid box is non-empty.
|
||||
|
||||
\cite "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
by Martin Eisemann, Thorsten Grosch, Stefan M<>ller and Marcus Magnor
|
||||
Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
University of Koblenz-Landau, Germany
|
||||
*/
|
||||
static bool __fastcall rayAABox(const Ray& ray, const AABox& box);
|
||||
|
||||
/** \brief Returns true if the intersection of the ray and the solid box is non-empty.
|
||||
|
||||
\param time If there is an intersection, set to the time to that intersection. If the ray origin is inside the box,
|
||||
this is a negative value indicating the distance backwards from the ray origin to the first intersection.
|
||||
\a time is not set if there is no intersection.
|
||||
|
||||
\cite Slope-Mul method from "Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
by Martin Eisemann, Thorsten Grosch, Stefan M<>ller and Marcus Magnor
|
||||
Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
University of Koblenz-Landau, Germany
|
||||
*/
|
||||
static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
1668
dep/g3dlite/include/G3D/KDTree.h
Normal file
1668
dep/g3dlite/include/G3D/KDTree.h
Normal file
File diff suppressed because it is too large
Load Diff
105
dep/g3dlite/include/G3D/Line.h
Normal file
105
dep/g3dlite/include/G3D/Line.h
Normal file
@@ -0,0 +1,105 @@
|
||||
/**
|
||||
@file Line.h
|
||||
|
||||
Line class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@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() {}
|
||||
|
||||
Line(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
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;
|
||||
|
||||
|
||||
/** Finds the closest point to the two lines.
|
||||
|
||||
@param minDist Returns the minimum distance between the lines.
|
||||
|
||||
@cite http://objectmix.com/graphics/133793-coordinates-closest-points-pair-skew-lines.html
|
||||
*/
|
||||
Vector3 closestPoint(const Line& B, float& minDist) const;
|
||||
|
||||
inline Vector3 closestPoint(const Line& B) const {
|
||||
float m;
|
||||
return closestPoint(B, m);
|
||||
}
|
||||
};
|
||||
|
||||
};// namespace
|
||||
|
||||
|
||||
#endif
|
||||
119
dep/g3dlite/include/G3D/LineSegment.h
Normal file
119
dep/g3dlite/include/G3D/LineSegment.h
Normal file
@@ -0,0 +1,119 @@
|
||||
/**
|
||||
@file LineSegment.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-02-08
|
||||
@edited 2008-02-02
|
||||
*/
|
||||
|
||||
#ifndef G3D_LINESEGMENT_H
|
||||
#define G3D_LINESEGMENT_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An finite segment of an infinite 3D line.
|
||||
*/
|
||||
class LineSegment {
|
||||
protected:
|
||||
|
||||
Point3 _point;
|
||||
|
||||
/** Not normalized */
|
||||
Vector3 direction;
|
||||
|
||||
LineSegment(const Point3& __point, const Vector3& _direction) : _point(__point), direction(_direction) {
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
LineSegment() : _point(Point3::zero()), direction(Vector3::zero()) {}
|
||||
|
||||
LineSegment(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
virtual ~LineSegment() {}
|
||||
|
||||
/**
|
||||
* Constructs a line from two (not equal) points.
|
||||
*/
|
||||
static LineSegment fromTwoPoints(const Point3 &point1, const Point3 &point2) {
|
||||
return LineSegment(point1, point2 - point1);
|
||||
}
|
||||
|
||||
/** Call with 0 or 1 */
|
||||
Point3 point(int i) const;
|
||||
|
||||
Point3 midpoint() const {
|
||||
return _point + direction * 0.5f;
|
||||
}
|
||||
|
||||
inline float length() const {
|
||||
return direction.magnitude();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the closest point on the line segment to point.
|
||||
*/
|
||||
Point3 closestPoint(const Point3 &point) const;
|
||||
|
||||
/**
|
||||
Returns the distance between point and the line
|
||||
*/
|
||||
double distance(const Point3& p) const {
|
||||
return (closestPoint(p) - p).magnitude();
|
||||
}
|
||||
|
||||
double distanceSquared(const Point3& p) const {
|
||||
return (closestPoint(p) - p).squaredMagnitude();
|
||||
}
|
||||
|
||||
/** Returns true if some part of this segment is inside the sphere */
|
||||
bool intersectsSolidSphere(const class Sphere& s) const;
|
||||
|
||||
Point3 randomPoint() const;
|
||||
|
||||
};
|
||||
|
||||
|
||||
class LineSegment2D {
|
||||
private:
|
||||
|
||||
Point2 m_origin;
|
||||
|
||||
/** Not normalized */
|
||||
Vector2 m_direction;
|
||||
|
||||
/** Length of m_direction */
|
||||
float m_length;
|
||||
|
||||
public:
|
||||
|
||||
LineSegment2D() {}
|
||||
|
||||
static LineSegment2D fromTwoPoints(const Point2& p0, const Vector2& p1);
|
||||
|
||||
/** Returns the intersection of these segements (including
|
||||
testing endpoints), or Point2::inf() if they do not intersect. */
|
||||
Point2 intersection(const LineSegment2D& other) const;
|
||||
|
||||
Point2 point(int i) const;
|
||||
|
||||
Point2 closestPoint(const Point2& Q) const;
|
||||
|
||||
float distance(const Point2& p) const;
|
||||
|
||||
float length() const;
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#endif
|
||||
109
dep/g3dlite/include/G3D/Log.h
Normal file
109
dep/g3dlite/include/G3D/Log.h
Normal file
@@ -0,0 +1,109 @@
|
||||
/**
|
||||
@file Log.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@cite Backtrace by Aaron Orenstein
|
||||
@created 2001-08-04
|
||||
@edited 2005-11-04
|
||||
*/
|
||||
|
||||
#ifndef G3D_LOG_H
|
||||
#define G3D_LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string>
|
||||
#include "G3D/platform.h"
|
||||
|
||||
#ifndef G3D_WINDOWS
|
||||
#include <stdarg.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Prints to the common system log, log.txt, which is usually
|
||||
in the working directory of the program. If your disk is
|
||||
not writable or is slow, it will attempt to write to "c:/tmp/log.txt" or
|
||||
"c:/temp/log.txt" on Windows systems instead.
|
||||
|
||||
Unlike printf or debugPrintf,
|
||||
this function guarantees that all output is committed before it returns.
|
||||
This is very useful for debugging a crash, which might hide the last few
|
||||
buffered print statements otherwise.
|
||||
|
||||
Many G3D routines write useful warnings and debugging information to the
|
||||
system log, which makes it a good first place to go when tracking down
|
||||
a problem.
|
||||
*/
|
||||
void logPrintf(const char* fmt, ...);
|
||||
|
||||
/** Does not flush the buffer; follow up with a logPrintf to force the flush. */
|
||||
void logLazyPrintf(const char* fmt, ...);
|
||||
|
||||
/**
|
||||
System log for debugging purposes. The first log opened
|
||||
is the "common log" and can be accessed with the static
|
||||
method common(). If you access common() and a common log
|
||||
does not yet exist, one is created for you.
|
||||
*/
|
||||
class Log {
|
||||
private:
|
||||
|
||||
/**
|
||||
Log messages go here.
|
||||
*/
|
||||
FILE* logFile;
|
||||
|
||||
std::string filename;
|
||||
|
||||
static Log* commonLog;
|
||||
|
||||
int stripFromStackBottom;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
@param stripFromStackBottom Number of call stacks to strip from the
|
||||
bottom of the stack when printing a trace. Useful for hiding
|
||||
routines like "main" and "WinMain". If the specified file cannot
|
||||
be opened for some reason, tries to open "c:/tmp/log.txt" or
|
||||
"c:/temp/log.txt" instead.
|
||||
*/
|
||||
Log(const std::string& filename = "log.txt",
|
||||
int stripFromStackBottom = 0);
|
||||
|
||||
virtual ~Log();
|
||||
|
||||
/**
|
||||
Returns the handle to the file log.
|
||||
*/
|
||||
FILE* getFile() const;
|
||||
|
||||
/**
|
||||
Marks the beginning of a logfile section.
|
||||
*/
|
||||
void section(const std::string& s);
|
||||
|
||||
/**
|
||||
Given arguments like printf, writes characters to the debug text overlay.
|
||||
*/
|
||||
// We want G3D_CHECK_PRINTF_ARGS here, but that conflicts with the
|
||||
// overload.
|
||||
void __cdecl printf(const char* fmt, ...) G3D_CHECK_PRINTF_METHOD_ARGS;
|
||||
|
||||
void __cdecl vprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
/** Does not flush */
|
||||
void __cdecl lazyvprintf(const char*, va_list argPtr) G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
|
||||
static Log* common();
|
||||
|
||||
static std::string getCommonLogFilename();
|
||||
|
||||
void print(const std::string& s);
|
||||
|
||||
|
||||
void println(const std::string& s);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
680
dep/g3dlite/include/G3D/Map2D.h
Normal file
680
dep/g3dlite/include/G3D/Map2D.h
Normal file
@@ -0,0 +1,680 @@
|
||||
/**
|
||||
@file Map2D.h
|
||||
|
||||
More flexible support than provided by G3D::GImage.
|
||||
|
||||
@maintainer Morgan McGuire, morgan@cs.brown.edu
|
||||
@created 2004-10-10
|
||||
@edited 2009-03-24
|
||||
*/
|
||||
#ifndef G3D_Map2D_h
|
||||
#define G3D_Map2D_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/vectorMath.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
#include "G3D/GThread.h"
|
||||
#include "G3D/Rect2D.h"
|
||||
#include "G3D/WrapMode.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
namespace _internal {
|
||||
|
||||
/** The default compute type for a type is the type itself. */
|
||||
template<typename Storage> class _GetComputeType {
|
||||
public:
|
||||
typedef Storage Type;
|
||||
};
|
||||
|
||||
} // _internal
|
||||
} // G3D
|
||||
|
||||
// This weird syntax is needed to support VC6, which doesn't
|
||||
// properly implement template overloading.
|
||||
#define DECLARE_COMPUTE_TYPE(StorageType, ComputeType) \
|
||||
namespace G3D { \
|
||||
namespace _internal { \
|
||||
template<> class _GetComputeType < StorageType > { \
|
||||
public: \
|
||||
typedef ComputeType Type; \
|
||||
}; \
|
||||
} \
|
||||
}
|
||||
|
||||
DECLARE_COMPUTE_TYPE( float32, float64)
|
||||
DECLARE_COMPUTE_TYPE( float64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( int8, float32)
|
||||
DECLARE_COMPUTE_TYPE( int16, float32)
|
||||
DECLARE_COMPUTE_TYPE( int32, float64)
|
||||
DECLARE_COMPUTE_TYPE( int64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( uint8, float32)
|
||||
DECLARE_COMPUTE_TYPE( uint16, float32)
|
||||
DECLARE_COMPUTE_TYPE( uint32, float64)
|
||||
DECLARE_COMPUTE_TYPE( uint64, float64)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector2, Vector2)
|
||||
DECLARE_COMPUTE_TYPE( Vector2int16, Vector2)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector3, Vector3)
|
||||
DECLARE_COMPUTE_TYPE( Vector3int16, Vector3)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Vector4, Vector4)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Color3, Color3)
|
||||
DECLARE_COMPUTE_TYPE( Color3uint8, Color3)
|
||||
|
||||
DECLARE_COMPUTE_TYPE( Color4, Color4)
|
||||
DECLARE_COMPUTE_TYPE( Color4uint8, Color4)
|
||||
#undef DECLARE_COMPUTE_TYPE
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Map of values across a discrete 2D plane. Can be thought of as a generic class for 2D images,
|
||||
allowing flexibility as to pixel format and convenient methods.
|
||||
In fact, the "pixels" can be any values
|
||||
on a grid that can be sensibly interpolated--RGB colors, scalars, 4D vectors, and so on.
|
||||
|
||||
Other "image" classes in G3D:
|
||||
|
||||
G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation.
|
||||
|
||||
G3D::shared_ptr<Texture> - Represents image on the graphics card (not directly readable on the CPU). Supports 2D, 3D, and a variety of interpolation methods, loads file formats.
|
||||
|
||||
G3D::Image3 - A subclass of Map2D<Color3> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image4 - A subclass of Map2D<Color4> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image3uint8 - A subclass of Map2D<Color3uint8> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
G3D::Image4uint8 - A subclass of Map2D<Color4uint8> that supports image loading and saving and conversion to Texture.
|
||||
|
||||
There are two type parameters-- the first (@ Storage) is the type
|
||||
used to store the "pixel" values efficiently and
|
||||
the second (@a Compute) is
|
||||
the type operated on by computation. The Compute::Compute(Storage&) constructor
|
||||
is used to convert between storage and computation types.
|
||||
@a Storage is often an integer version of @a Compute, for example
|
||||
<code>Map2D<double, uint8></code>. By default, the computation type is:
|
||||
|
||||
<pre>
|
||||
Storage Computation
|
||||
|
||||
uint8 float32
|
||||
uint16 float32
|
||||
uint32 float64
|
||||
uint64 float64
|
||||
|
||||
int8 float32
|
||||
int16 float32
|
||||
int32 float64
|
||||
int64 float64
|
||||
|
||||
float32 float64
|
||||
float64 float64
|
||||
|
||||
Vector2 Vector2
|
||||
Vector2int16 Vector2
|
||||
|
||||
Vector3 Vector3
|
||||
Vector3int16 Vector3
|
||||
|
||||
Vector4 Vector4
|
||||
|
||||
Color3 Color3
|
||||
Color3uint8 Color3
|
||||
|
||||
Color4 Color4
|
||||
Color4uint8 Color4
|
||||
</pre>
|
||||
Any other storage type defaults to itself as the computation type.
|
||||
|
||||
The computation type can be any that
|
||||
supports lerp, +, -, *, /, and an empty constructor.
|
||||
|
||||
Assign value:
|
||||
|
||||
<code>im->set(x, y, 7);</code> or
|
||||
<code>im->get(x, y) = 7;</code>
|
||||
|
||||
Read value:
|
||||
|
||||
<code>int c = im(x, y);</code>
|
||||
|
||||
Can also sample with nearest neighbor, bilinear, and bicubic
|
||||
interpolation.
|
||||
|
||||
Sampling follows OpenGL conventions, where
|
||||
pixel values represent grid points and (0.5, 0.5) is half-way
|
||||
between two vertical and two horizontal grid points.
|
||||
To draw an image of dimensions w x h with nearest neighbor
|
||||
sampling, render pixels from [0, 0] to [w - 1, h - 1].
|
||||
|
||||
Under the WrapMode::CLAMP wrap mode, the value of bilinear interpolation
|
||||
becomes constant outside [1, w - 2] horizontally. Nearest neighbor
|
||||
interpolation is constant outside [0, w - 1] and bicubic outside
|
||||
[3, w - 4]. The class does not offer quadratic interpolation because
|
||||
the interpolation filter could not center over a pixel.
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
template< typename Storage,
|
||||
typename Compute = typename G3D::_internal::_GetComputeType<Storage>::Type>
|
||||
class Map2D : public ReferenceCountedObject {
|
||||
|
||||
//
|
||||
// It doesn't make sense to automatically convert from Compute back to Storage
|
||||
// because the rounding rule (and scaling) is application dependent.
|
||||
// Thus the interpolation methods all return type Compute.
|
||||
//
|
||||
|
||||
public:
|
||||
|
||||
typedef Storage StorageType;
|
||||
typedef Compute ComputeType;
|
||||
typedef Map2D<Storage, Compute> Type;
|
||||
typedef shared_ptr<Map2D> Ref;
|
||||
|
||||
protected:
|
||||
|
||||
Storage ZERO;
|
||||
|
||||
/** Width, in pixels. */
|
||||
uint32 w;
|
||||
|
||||
/** Height, in pixels. */
|
||||
uint32 h;
|
||||
|
||||
WrapMode _wrapMode;
|
||||
|
||||
/** 0 if no mutating method has been invoked
|
||||
since the last call to setChanged(); */
|
||||
AtomicInt32 m_changed;
|
||||
|
||||
Array<Storage> data;
|
||||
|
||||
/** Handles the exceptional cases from get */
|
||||
const Storage& slowGet(int x, int y, WrapMode wrap) {
|
||||
switch (wrap) {
|
||||
case WrapMode::CLAMP:
|
||||
return fastGet(iClamp(x, 0, w - 1), iClamp(y, 0, h - 1));
|
||||
|
||||
case WrapMode::TILE:
|
||||
return fastGet(iWrap(x, w), iWrap(y, h));
|
||||
|
||||
case WrapMode::ZERO:
|
||||
return ZERO;
|
||||
|
||||
case WrapMode::ERROR:
|
||||
alwaysAssertM(((uint32)x < w) && ((uint32)y < h),
|
||||
format("Index out of bounds: (%d, %d), w = %d, h = %d",
|
||||
x, y, w, h));
|
||||
|
||||
// intentionally fall through
|
||||
case WrapMode::IGNORE:
|
||||
// intentionally fall through
|
||||
default:
|
||||
{
|
||||
static Storage temp;
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
|
||||
inline const Storage& fastGet(int x, int y) const {
|
||||
debugAssert(((uint32)x < w) && ((uint32)y < h));
|
||||
return data[x + y * w];
|
||||
}
|
||||
|
||||
/** Unsafe access to the underlying data structure with no wrapping support; requires that (x, y) is in bounds. */
|
||||
inline void fastSet(int x, int y, const Storage& v) {
|
||||
debugAssert(((uint32)x < w) && ((uint32)y < h));
|
||||
data[x + y * w] = v;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Given four control points and a value on the range [0, 1)
|
||||
evaluates the Catmull-rom spline between the times of the
|
||||
middle two control points */
|
||||
Compute bicubic(const Compute* ctrl, double s) const {
|
||||
|
||||
// f = B * S * ctrl'
|
||||
|
||||
// B matrix: Catmull-Rom spline basis
|
||||
static const double B[4][4] = {
|
||||
{ 0.0, -0.5, 1.0, -0.5},
|
||||
{ 1.0, 0.0, -2.5, 1.5},
|
||||
{ 0.0, 0.5, 2.0, -1.5},
|
||||
{ 0.0, 0.0, -0.5, 0.5}};
|
||||
|
||||
// S: Powers of the fraction
|
||||
double S[4];
|
||||
double s2 = s * s;
|
||||
S[0] = 1.0;
|
||||
S[1] = s;
|
||||
S[2] = s2;
|
||||
S[3] = s2 * s;
|
||||
|
||||
Compute sum(ZERO);
|
||||
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
double coeff = 0.0;
|
||||
for (int power = 0; power < 4; ++power) {
|
||||
coeff += B[c][power] * S[power];
|
||||
}
|
||||
sum += ctrl[c] * coeff;
|
||||
}
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
||||
|
||||
Map2D(int w, int h, WrapMode wrap) : w(0), h(0), _wrapMode(wrap), m_changed(1) {
|
||||
ZERO = Storage(Compute(Storage()) * 0);
|
||||
resize(w, h);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Although Map2D is not threadsafe (except for the setChanged() method),
|
||||
you can use this mutex to create your own threadsafe access to a Map2D.
|
||||
Not used by the default implementation.
|
||||
*/
|
||||
GMutex mutex;
|
||||
|
||||
static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) {
|
||||
return Ref(new Map2D(w, h, wrap));
|
||||
}
|
||||
|
||||
/** Resizes without clearing, leaving garbage.
|
||||
*/
|
||||
void resize(uint32 newW, uint32 newH) {
|
||||
if ((newW != w) || (newH != h)) {
|
||||
w = newW;
|
||||
h = newH;
|
||||
data.resize(w * h);
|
||||
setChanged(true);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if this map has been written to since the last call to setChanged(false).
|
||||
This is useful if you are caching a texture map other value that must be recomputed
|
||||
whenever this changes.
|
||||
*/
|
||||
bool changed() {
|
||||
return m_changed.value() != 0;
|
||||
}
|
||||
|
||||
/** Set/unset the changed flag. */
|
||||
void setChanged(bool c) {
|
||||
m_changed = c ? 1 : 0;
|
||||
}
|
||||
|
||||
/** Returns a pointer to the underlying row-major data. There is no padding at the end of the row.
|
||||
Be careful--this will be reallocated during a resize. You should call setChanged(true) if you mutate the array.*/
|
||||
Storage* getCArray() {
|
||||
return data.getCArray();
|
||||
}
|
||||
|
||||
|
||||
const Storage* getCArray() const {
|
||||
return data.getCArray();
|
||||
}
|
||||
|
||||
|
||||
/** Row-major array. You should call setChanged(true) if you mutate the array. */
|
||||
Array<Storage>& getArray() {
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
const Array<Storage>& getArray() const {
|
||||
return data;
|
||||
}
|
||||
|
||||
/** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
|
||||
inline bool inBounds(int x, int y) const {
|
||||
return (((uint32)x < w) && ((uint32)y < h));
|
||||
}
|
||||
|
||||
/** is (x, y) strictly within the image bounds, or will it trigger some kind of wrap mode */
|
||||
inline bool inBounds(const Vector2int16& v) const {
|
||||
return inBounds(v.x, v.y);
|
||||
}
|
||||
|
||||
/** Get the value at (x, y).
|
||||
|
||||
Note that the type of image->get(x, y) is
|
||||
the storage type, not the computation
|
||||
type. If the constructor promoting Storage to Compute rescales values
|
||||
(as, for example Color3(Color3uint8&) does), this will not match the value
|
||||
returned by Map2D::nearest.
|
||||
*/
|
||||
inline const Storage& get(int x, int y, WrapMode wrap) const {
|
||||
if (((uint32)x < w) && ((uint32)y < h)) {
|
||||
return data[x + y * w];
|
||||
} else {
|
||||
// Remove the const to allow a slowGet on this object
|
||||
// (we're returning a const reference so this is ok)
|
||||
return const_cast<Type*>(this)->slowGet(x, y, wrap);
|
||||
}
|
||||
# ifndef G3D_WINDOWS
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline const Storage& get(int x, int y) const {
|
||||
return get(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline const Storage& get(const Vector2int16& p) const {
|
||||
return get(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
inline const Storage& get(const Vector2int16& p, WrapMode wrap) const {
|
||||
return get(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
inline Storage& get(int x, int y, WrapMode wrap) {
|
||||
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y, wrap));
|
||||
# ifndef G3D_WINDOWS
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline Storage& get(int x, int y) {
|
||||
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y));
|
||||
# ifndef G3D_WINDOWS
|
||||
// gcc gives a useless warning that the above code might reach the end of the function;
|
||||
// we use this line to supress the warning.
|
||||
return ZERO;
|
||||
# endif
|
||||
}
|
||||
|
||||
inline Storage& get(const Vector2int16& p) {
|
||||
return get(p.x, p.y);
|
||||
}
|
||||
|
||||
/** Sets the changed flag to true */
|
||||
inline void set(const Vector2int16& p, const Storage& v) {
|
||||
set(p.x, p.y, v);
|
||||
}
|
||||
|
||||
/** Sets the changed flag to true */
|
||||
void set(int x, int y, const Storage& v, WrapMode wrap) {
|
||||
setChanged(true);
|
||||
if (((uint32)x < w) && ((uint32)y < h)) {
|
||||
// In bounds, wrapping isn't an issue.
|
||||
data[x + y * w] = v;
|
||||
} else {
|
||||
const_cast<Storage&>(slowGet(x, y, wrap)) = v;
|
||||
}
|
||||
}
|
||||
|
||||
void set(int x, int y, const Storage& v) {
|
||||
set(x, y, v, _wrapMode);
|
||||
}
|
||||
|
||||
|
||||
void setAll(const Storage& v) {
|
||||
for(int i = 0; i < data.size(); ++i) {
|
||||
data[i] = v;
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
/** Copy values from \a src, which must have the same size */
|
||||
template<class T>
|
||||
void set(const shared_ptr<Map2D<Storage, T> >& src) {
|
||||
debugAssert(src->width() == width());
|
||||
debugAssert(src->height() == height());
|
||||
const Array<Storage>& s = src->data;
|
||||
int N = w * h;
|
||||
for (int i = 0; i < N; ++i) {
|
||||
data[i] = s[i];
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
/** flips if @a flip is true*/
|
||||
void maybeFlipVertical(bool flip) {
|
||||
if (flip) {
|
||||
flipVertical();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void flipVertical() {
|
||||
int halfHeight = h/2;
|
||||
Storage* d = data.getCArray();
|
||||
for (int y = 0; y < halfHeight; ++y) {
|
||||
int o1 = y * w;
|
||||
int o2 = (h - y - 1) * w;
|
||||
for (int x = 0; x < (int)w; ++x) {
|
||||
int i1 = o1 + x;
|
||||
int i2 = o2 + x;
|
||||
Storage temp = d[i1];
|
||||
d[i1] = d[i2];
|
||||
d[i2] = temp;
|
||||
}
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
virtual void flipHorizontal() {
|
||||
int halfWidth = w / 2;
|
||||
Storage* d = data.getCArray();
|
||||
for (int x = 0; x < halfWidth; ++x) {
|
||||
for (int y = 0; y < (int)h; ++y) {
|
||||
int i1 = y * w + x;
|
||||
int i2 = y * w + (w - x - 1);
|
||||
Storage temp = d[i1];
|
||||
d[i1] = d[i2];
|
||||
d[i2] = temp;
|
||||
}
|
||||
}
|
||||
setChanged(true);
|
||||
}
|
||||
|
||||
/**
|
||||
Crops this map so that it only contains pixels between (x, y) and (x + w - 1, y + h - 1) inclusive.
|
||||
*/
|
||||
virtual void crop(int newX, int newY, int newW, int newH) {
|
||||
alwaysAssertM(newX + newW <= (int)w, "Cannot grow when cropping");
|
||||
alwaysAssertM(newY + newH <= (int)h, "Cannot grow when cropping");
|
||||
alwaysAssertM(newX >= 0 && newY >= 0, "Origin out of bounds.");
|
||||
|
||||
// Always safe to copy towards the upper left, provided
|
||||
// that we're iterating towards the lower right. This lets us avoid
|
||||
// reallocating the underlying array.
|
||||
for (int y = 0; y < newH; ++y) {
|
||||
for (int x = 0; x < newW; ++x) {
|
||||
data[x + y * newW] = data[(x + newX) + (y + newY) * w];
|
||||
}
|
||||
}
|
||||
|
||||
resize(newW, newH);
|
||||
}
|
||||
|
||||
/** iRounds to the nearest x0 and y0. */
|
||||
virtual void crop(const Rect2D& rect) {
|
||||
crop(iRound(rect.x0()), iRound(rect.y0()), iRound(rect.x1()) - iRound(rect.x0()), iRound(rect.y1()) - iRound(rect.y0()));
|
||||
}
|
||||
|
||||
/** Returns the nearest neighbor. Pixel values are considered
|
||||
to be at the upper left corner, so <code>image->nearest(x, y) == image(x, y)</code>
|
||||
*/
|
||||
inline Compute nearest(float x, float y, WrapMode wrap) const {
|
||||
int ix = iRound(x);
|
||||
int iy = iRound(y);
|
||||
return Compute(get(ix, iy, wrap));
|
||||
}
|
||||
|
||||
inline Compute nearest(float x, float y) const {
|
||||
return nearest(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute nearest(const Vector2& p) const {
|
||||
return nearest(p.x, p.y);
|
||||
}
|
||||
|
||||
/** Returns the average value of all elements of the map */
|
||||
Compute average() const {
|
||||
if ((w == 0) || (h == 0)) {
|
||||
return ZERO;
|
||||
}
|
||||
|
||||
// To avoid overflows, compute the average of row averages
|
||||
|
||||
Compute rowSum = ZERO;
|
||||
for (unsigned int y = 0; y < h; ++y) {
|
||||
Compute sum = ZERO;
|
||||
int offset = y * w;
|
||||
for (unsigned int x = 0; x < w; ++x) {
|
||||
sum += Compute(data[offset + x]);
|
||||
}
|
||||
rowSum += sum * (1.0f / w);
|
||||
}
|
||||
|
||||
return rowSum * (1.0f / h);
|
||||
}
|
||||
|
||||
/**
|
||||
Needs to access elements from (floor(x), floor(y))
|
||||
to (floor(x) + 1, floor(y) + 1) and will use
|
||||
the wrap mode appropriately (possibly generating
|
||||
out of bounds errors).
|
||||
|
||||
Guaranteed to match nearest(x, y) at integers. */
|
||||
Compute bilinear(float x, float y, WrapMode wrap) const {
|
||||
const int i = iFloor(x);
|
||||
const int j = iFloor(y);
|
||||
|
||||
const float fX = x - i;
|
||||
const float fY = y - j;
|
||||
|
||||
// Horizontal interpolation, first row
|
||||
const Compute& t0 = get(i, j, wrap);
|
||||
const Compute& t1 = get(i + 1, j, wrap);
|
||||
|
||||
// Horizontal interpolation, second row
|
||||
const Compute& t2 = get(i, j + 1, wrap);
|
||||
const Compute& t3 = get(i + 1, j + 1, wrap);
|
||||
|
||||
const Compute& A = lerp(t0, t1, fX);
|
||||
const Compute& B = lerp(t2, t3, fX);
|
||||
|
||||
// Vertical interpolation
|
||||
return lerp(A, B, fY);
|
||||
}
|
||||
|
||||
Compute bilinear(float x, float y) const {
|
||||
return bilinear(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bilinear(const Vector2& p) const {
|
||||
return bilinear(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bilinear(const Vector2& p, WrapMode wrap) const {
|
||||
return bilinear(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
/**
|
||||
Uses Catmull-Rom splines to interpolate between grid
|
||||
values. Guaranteed to match nearest(x, y) at integers.
|
||||
*/
|
||||
Compute bicubic(float x, float y, WrapMode wrap) const {
|
||||
int i = iFloor(x);
|
||||
int j = iFloor(y);
|
||||
float fX = x - i;
|
||||
float fY = y - j;
|
||||
|
||||
Compute vsample[4];
|
||||
for (int v = 0; v < 4; ++v) {
|
||||
|
||||
// Horizontal interpolation
|
||||
Compute hsample[4];
|
||||
for (int u = 0; u < 4; ++u) {
|
||||
hsample[u] = Compute(get(i + u - 1, j + v - 1, wrap));
|
||||
}
|
||||
|
||||
vsample[v] = bicubic(hsample, fX);
|
||||
}
|
||||
|
||||
// Vertical interpolation
|
||||
return bicubic(vsample, fY);
|
||||
}
|
||||
|
||||
Compute bicubic(float x, float y) const {
|
||||
return bicubic(x, y, _wrapMode);
|
||||
}
|
||||
|
||||
inline Compute bicubic(const Vector2& p, WrapMode wrap) const {
|
||||
return bicubic(p.x, p.y, wrap);
|
||||
}
|
||||
|
||||
inline Compute bicubic(const Vector2& p) const {
|
||||
return bicubic(p.x, p.y, _wrapMode);
|
||||
}
|
||||
|
||||
/** Pixel width */
|
||||
inline int32 width() const {
|
||||
return (int32)w;
|
||||
}
|
||||
|
||||
|
||||
/** Pixel height */
|
||||
inline int32 height() const {
|
||||
return (int32)h;
|
||||
}
|
||||
|
||||
|
||||
/** Dimensions in pixels */
|
||||
Vector2int16 size() const {
|
||||
return Vector2int16(w, h);
|
||||
}
|
||||
|
||||
/** Rectangle from (0, 0) to (w, h) */
|
||||
Rect2D rect2DBounds() const {
|
||||
return Rect2D::xywh(0, 0, w, h);
|
||||
}
|
||||
|
||||
/** Number of bytes occupied by the image data and this structure */
|
||||
size_t sizeInMemory() const {
|
||||
return data.size() * sizeof(Storage) + sizeof(*this);
|
||||
}
|
||||
|
||||
|
||||
WrapMode wrapMode() const {
|
||||
return _wrapMode;
|
||||
}
|
||||
|
||||
|
||||
void setWrapMode(WrapMode m) {
|
||||
_wrapMode = m;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
#endif // G3D_IMAGE_H
|
||||
637
dep/g3dlite/include/G3D/Matrix.h
Normal file
637
dep/g3dlite/include/G3D/Matrix.h
Normal file
@@ -0,0 +1,637 @@
|
||||
/**
|
||||
@file Matrix.h
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-10-23
|
||||
@edited 2007-07-18
|
||||
*/
|
||||
|
||||
#ifndef G3D_MATRIX_H
|
||||
#define G3D_MATRIX_H
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
N x M matrix.
|
||||
|
||||
The actual data is tracked internally by a reference counted pointer;
|
||||
it is efficient to pass and assign Matrix objects because no data is actually copied.
|
||||
This avoids the headache of pointers and allows natural math notation:
|
||||
|
||||
<PRE>
|
||||
Matrix A, B, C;
|
||||
// ...
|
||||
|
||||
C = A * f(B);
|
||||
C = C.inverse();
|
||||
|
||||
A = Matrix::identity(4);
|
||||
C = A;
|
||||
C.set(0, 0, 2.0); // Triggers a copy of the data so that A remains unchanged.
|
||||
|
||||
// etc.
|
||||
|
||||
</PRE>
|
||||
|
||||
The Matrix::debugNumCopyOps and Matrix::debugNumAllocOps counters
|
||||
increment every time an operation forces the copy and allocation of matrices. You
|
||||
can use these to detect slow operations when efficiency is a major concern.
|
||||
|
||||
Some methods accept an output argument instead of returning a value. For example,
|
||||
<CODE>A = B.transpose()</CODE> can also be invoked as <CODE>B.transpose(A)</CODE>.
|
||||
The latter may be more efficient, since Matrix may be able to re-use the storage of
|
||||
A (if it has approximatly the right size and isn't currently shared with another matrix).
|
||||
|
||||
@sa G3D::Matrix3, G3D::Matrix4, G3D::Vector2, G3D::Vector3, G3D::Vector4, G3D::CoordinateFrame
|
||||
|
||||
@beta
|
||||
*/
|
||||
class Matrix {
|
||||
public:
|
||||
/**
|
||||
Internal precision. Currently float, but this may become a templated class in the future
|
||||
to allow operations like Matrix<double> and Matrix<ComplexFloat>.
|
||||
|
||||
Not necessarily a plain-old-data type (e.g., could ComplexFloat), but must be something
|
||||
with no constructor, that can be safely memcpyd, and that has a bit pattern of all zeros
|
||||
when zero.*/
|
||||
typedef float T;
|
||||
|
||||
/** Incremented every time the elements of a matrix are copied. Useful for profiling your
|
||||
own code that uses Matrix to determine when it is slow due to copying.*/
|
||||
static int debugNumCopyOps;
|
||||
|
||||
/** Incremented every time a new matrix object is allocated. Useful for profiling your
|
||||
own code that uses Matrix to determine when it is slow due to allocation.*/
|
||||
static int debugNumAllocOps;
|
||||
|
||||
private:
|
||||
public:
|
||||
|
||||
/** Used internally by Matrix.
|
||||
|
||||
Does not throw exceptions-- assumes the caller has taken care of
|
||||
argument checking. */
|
||||
class Impl : public ReferenceCountedObject {
|
||||
public:
|
||||
|
||||
static void* operator new(size_t size) {
|
||||
return System::malloc(size);
|
||||
}
|
||||
|
||||
static void operator delete(void* p) {
|
||||
System::free(p);
|
||||
}
|
||||
|
||||
~Impl();
|
||||
|
||||
private:
|
||||
friend class Matrix;
|
||||
|
||||
/** elt[r][c] = the element. Pointers into data.*/
|
||||
T** elt;
|
||||
|
||||
/** Row major data for the entire matrix. */
|
||||
T* data;
|
||||
|
||||
/** The number of rows */
|
||||
int R;
|
||||
|
||||
/** The number of columns */
|
||||
int C;
|
||||
|
||||
int dataSize;
|
||||
|
||||
/** If R*C is much larger or smaller than the current, deletes all previous data
|
||||
and resets to random data. Otherwise re-uses existing memory and just resets
|
||||
R, C, and the row pointers. */
|
||||
void setSize(int newRows, int newCols);
|
||||
|
||||
inline Impl() : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {}
|
||||
|
||||
Impl(const Matrix3& M);
|
||||
|
||||
Impl(const Matrix4& M);
|
||||
|
||||
inline Impl(int r, int c) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
|
||||
setSize(r, c);
|
||||
}
|
||||
|
||||
Impl& operator=(const Impl& m);
|
||||
|
||||
inline Impl(const Impl& B) : elt(NULL), data(NULL), R(0), C(0), dataSize(0) {
|
||||
// Use the assignment operator
|
||||
*this = B;
|
||||
}
|
||||
|
||||
void setZero();
|
||||
|
||||
inline void set(int r, int c, T v) {
|
||||
debugAssert(r < R);
|
||||
debugAssert(c < C);
|
||||
elt[r][c] = v;
|
||||
}
|
||||
|
||||
inline const T& get(int r, int c) const {
|
||||
debugAssert(r < R);
|
||||
debugAssert(c < C);
|
||||
return elt[r][c];
|
||||
}
|
||||
|
||||
/** Multiplies this by B and puts the result in out. */
|
||||
void mul(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void add(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void add(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void sub(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void sub(T B, Impl& out) const;
|
||||
|
||||
/** B - this */
|
||||
void lsub(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void arrayMul(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void mul(T B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void arrayDiv(const Impl& B, Impl& out) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void div(T B, Impl& out) const;
|
||||
|
||||
void negate(Impl& out) const;
|
||||
|
||||
/** Slow way of computing an inverse; for reference */
|
||||
void inverseViaAdjoint(Impl& out) const;
|
||||
|
||||
/** Use Gaussian elimination with pivots to solve for the inverse destructively in place. */
|
||||
void inverseInPlaceGaussJordan();
|
||||
|
||||
void adjoint(Impl& out) const;
|
||||
|
||||
/** Matrix of all cofactors */
|
||||
void cofactor(Impl& out) const;
|
||||
|
||||
/**
|
||||
Cofactor [r][c] is defined as C[r][c] = -1 ^(r+c) * det(A[r][c]),
|
||||
where A[r][c] is the (R-1)x(C-1) matrix formed by removing row r and
|
||||
column c from the original matrix.
|
||||
*/
|
||||
T cofactor(int r, int c) const;
|
||||
|
||||
/** Ok if out == this or out == B */
|
||||
void transpose(Impl& out) const;
|
||||
|
||||
T determinant() const;
|
||||
|
||||
/** Determinant computed without the given row and column */
|
||||
T determinant(int r, int c) const;
|
||||
|
||||
void arrayLog(Impl& out) const;
|
||||
|
||||
void arrayExp(Impl& out) const;
|
||||
|
||||
void arraySqrt(Impl& out) const;
|
||||
|
||||
void arrayCos(Impl& out) const;
|
||||
|
||||
void arraySin(Impl& out) const;
|
||||
|
||||
void swapRows(int r0, int r1);
|
||||
|
||||
void swapAndNegateCols(int c0, int c1);
|
||||
|
||||
void mulRow(int r, const T& v);
|
||||
|
||||
void abs(Impl& out) const;
|
||||
|
||||
/** Makes a (R-1)x(C-1) copy of this matrix */
|
||||
void withoutRowAndCol(int excludeRow, int excludeCol, Impl& out) const;
|
||||
|
||||
bool anyNonZero() const;
|
||||
|
||||
bool allNonZero() const;
|
||||
|
||||
void setRow(int r, const T* vals);
|
||||
|
||||
void setCol(int c, const T* vals);
|
||||
};
|
||||
private:
|
||||
|
||||
typedef shared_ptr<Impl> ImplRef;
|
||||
|
||||
ImplRef impl;
|
||||
|
||||
inline Matrix(ImplRef i) : impl(i) {}
|
||||
inline Matrix(Impl* i) : impl(ImplRef(i)) {}
|
||||
|
||||
/** Used by SVD */
|
||||
class SortRank {
|
||||
public:
|
||||
T value;
|
||||
int col;
|
||||
|
||||
inline bool operator>(const SortRank& x) const {
|
||||
return x.value > value;
|
||||
}
|
||||
|
||||
inline bool operator<(const SortRank& x) const {
|
||||
return x.value < value;
|
||||
}
|
||||
|
||||
inline bool operator>=(const SortRank& x) const {
|
||||
return x.value >= value;
|
||||
}
|
||||
|
||||
inline bool operator<=(const SortRank& x) const {
|
||||
return x.value <= value;
|
||||
}
|
||||
|
||||
inline bool operator==(const SortRank& x) const {
|
||||
return x.value == value;
|
||||
}
|
||||
|
||||
inline bool operator!=(const SortRank& x) const {
|
||||
return x.value != value;
|
||||
}
|
||||
};
|
||||
|
||||
Matrix vectorPseudoInverse() const;
|
||||
Matrix partitionPseudoInverse() const;
|
||||
Matrix colPartPseudoInverse() const;
|
||||
Matrix rowPartPseudoInverse() const;
|
||||
|
||||
Matrix col2PseudoInverse(const Matrix& B) const;
|
||||
Matrix col3PseudoInverse(const Matrix& B) const;
|
||||
Matrix col4PseudoInverse(const Matrix& B) const;
|
||||
Matrix row2PseudoInverse(const Matrix& B) const;
|
||||
Matrix row3PseudoInverse(const Matrix& B) const;
|
||||
Matrix row4PseudoInverse(const Matrix& B) const;
|
||||
|
||||
public:
|
||||
|
||||
Matrix() : impl(new Impl(0, 0)) {}
|
||||
|
||||
Matrix(const Matrix3& M) : impl(new Impl(M)) {}
|
||||
|
||||
Matrix(const Matrix4& M) : impl(new Impl(M)) {}
|
||||
|
||||
template<class S>
|
||||
static Matrix fromDiagonal(const Array<S>& d) {
|
||||
Matrix D = zero(d.length(), d.length());
|
||||
for (int i = 0; i < d.length(); ++i) {
|
||||
D.set(i, i, d[i]);
|
||||
}
|
||||
return D;
|
||||
}
|
||||
|
||||
static Matrix fromDiagonal(const Matrix& d);
|
||||
|
||||
/** Returns a new matrix that is all zero. */
|
||||
Matrix(int R, int C) : impl(new Impl(R, C)) {
|
||||
impl->setZero();
|
||||
}
|
||||
|
||||
/** Returns a new matrix that is all zero. */
|
||||
static Matrix zero(int R, int C);
|
||||
|
||||
/** Returns a new matrix that is all one. */
|
||||
static Matrix one(int R, int C);
|
||||
|
||||
/** Returns a new identity matrix */
|
||||
static Matrix identity(int N);
|
||||
|
||||
/** Uniformly distributed values between zero and one. */
|
||||
static Matrix random(int R, int C);
|
||||
|
||||
/** The number of rows */
|
||||
inline int rows() const {
|
||||
return impl->R;
|
||||
}
|
||||
|
||||
/** Number of columns */
|
||||
inline int cols() const {
|
||||
return impl->C;
|
||||
}
|
||||
|
||||
/** Generally more efficient than A * B */
|
||||
Matrix& operator*=(const T& B);
|
||||
|
||||
/** Generally more efficient than A / B */
|
||||
Matrix& operator/=(const T& B);
|
||||
|
||||
/** Generally more efficient than A + B */
|
||||
Matrix& operator+=(const T& B);
|
||||
|
||||
/** Generally more efficient than A - B */
|
||||
Matrix& operator-=(const T& B);
|
||||
|
||||
/** No performance advantage over A * B because
|
||||
matrix multiplication requires intermediate
|
||||
storage. */
|
||||
Matrix& operator*=(const Matrix& B);
|
||||
|
||||
/** Generally more efficient than A + B */
|
||||
Matrix& operator+=(const Matrix& B);
|
||||
|
||||
/** Generally more efficient than A - B */
|
||||
Matrix& operator-=(const Matrix& B);
|
||||
|
||||
/** Returns a new matrix that is a subset of this one,
|
||||
from r1:r2 to c1:c2, inclusive.*/
|
||||
Matrix subMatrix(int r1, int r2, int c1, int c2) const;
|
||||
|
||||
/** Matrix multiplication. To perform element-by-element multiplication,
|
||||
see arrayMul. */
|
||||
inline Matrix operator*(const Matrix& B) const {
|
||||
Matrix C(impl->R, B.impl->C);
|
||||
impl->mul(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A *= B, which is more efficient in many cases */
|
||||
inline Matrix operator*(const T& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->mul(B, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A += B, which is more efficient in many cases */
|
||||
inline Matrix operator+(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->add(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A -= B, which is more efficient in many cases */
|
||||
inline Matrix operator-(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->sub(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A += B, which is more efficient in many cases */
|
||||
inline Matrix operator+(const T& v) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->add(v, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
/** See also A -= B, which is more efficient in many cases */
|
||||
inline Matrix operator-(const T& v) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->sub(v, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
|
||||
Matrix operator>(const T& scalar) const;
|
||||
|
||||
Matrix operator<(const T& scalar) const;
|
||||
|
||||
Matrix operator>=(const T& scalar) const;
|
||||
|
||||
Matrix operator<=(const T& scalar) const;
|
||||
|
||||
Matrix operator==(const T& scalar) const;
|
||||
|
||||
Matrix operator!=(const T& scalar) const;
|
||||
|
||||
/** scalar B - this */
|
||||
inline Matrix lsub(const T& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->lsub(B, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
inline Matrix arrayMul(const Matrix& B) const {
|
||||
Matrix C(impl->R, impl->C);
|
||||
impl->arrayMul(*B.impl, *C.impl);
|
||||
return C;
|
||||
}
|
||||
|
||||
Matrix3 toMatrix3() const;
|
||||
|
||||
Matrix4 toMatrix4() const;
|
||||
|
||||
Vector2 toVector2() const;
|
||||
|
||||
Vector3 toVector3() const;
|
||||
|
||||
Vector4 toVector4() const;
|
||||
|
||||
/** Mutates this */
|
||||
void arrayMulInPlace(const Matrix& B);
|
||||
|
||||
/** Mutates this */
|
||||
void arrayDivInPlace(const Matrix& B);
|
||||
|
||||
// Declares an array unary method and its explicit-argument counterpart
|
||||
# define DECLARE_METHODS_1(method)\
|
||||
inline Matrix method() const {\
|
||||
Matrix C(impl->R, impl->C);\
|
||||
impl->method(*C.impl);\
|
||||
return C;\
|
||||
}\
|
||||
void method(Matrix& out) const;
|
||||
|
||||
|
||||
DECLARE_METHODS_1(abs)
|
||||
DECLARE_METHODS_1(arrayLog)
|
||||
DECLARE_METHODS_1(arrayExp)
|
||||
DECLARE_METHODS_1(arraySqrt)
|
||||
DECLARE_METHODS_1(arrayCos)
|
||||
DECLARE_METHODS_1(arraySin)
|
||||
DECLARE_METHODS_1(negate)
|
||||
|
||||
# undef DECLARE_METHODS_1
|
||||
|
||||
inline Matrix operator-() const {
|
||||
return negate();
|
||||
}
|
||||
|
||||
/**
|
||||
A<SUP>-1</SUP> computed using the Gauss-Jordan algorithm,
|
||||
for square matrices.
|
||||
Run time is <I>O(R<sup>3</sup>)</I>, where <I>R</i> is the
|
||||
number of rows.
|
||||
*/
|
||||
inline Matrix inverse() const {
|
||||
Impl* A = new Impl(*impl);
|
||||
A->inverseInPlaceGaussJordan();
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
inline T determinant() const {
|
||||
return impl->determinant();
|
||||
}
|
||||
|
||||
/**
|
||||
A<SUP>T</SUP>
|
||||
*/
|
||||
inline Matrix transpose() const {
|
||||
Impl* A = new Impl(cols(), rows());
|
||||
impl->transpose(*A);
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
/** Transpose in place; more efficient than transpose */
|
||||
void transpose(Matrix& out) const;
|
||||
|
||||
inline Matrix adjoint() const {
|
||||
Impl* A = new Impl(cols(), rows());
|
||||
impl->adjoint(*A);
|
||||
return Matrix(A);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Computes the Moore-Penrose pseudo inverse, equivalent to
|
||||
(A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>). The SVD method is used
|
||||
for performance when the matrix has more than four rows or columns
|
||||
|
||||
\cite http://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse
|
||||
|
||||
\param tolerance Use -1 for automatic tolerance.
|
||||
*/
|
||||
Matrix pseudoInverse(float tolerance = -1) const;
|
||||
|
||||
/** Called from pseudoInverse when the matrix has size > 4 along some dimension.*/
|
||||
Matrix svdPseudoInverse(float tolerance = -1) const;
|
||||
|
||||
/**
|
||||
(A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
|
||||
using Gauss-Jordan elimination.
|
||||
*/
|
||||
inline Matrix gaussJordanPseudoInverse() const {
|
||||
Matrix trans = transpose();
|
||||
return (trans * (*this)).inverse() * trans;
|
||||
}
|
||||
|
||||
/** Singular value decomposition. Factors into three matrices
|
||||
such that @a this = @a U * fromDiagonal(@a d) * @a V.transpose().
|
||||
|
||||
The matrix must have at least as many rows as columns.
|
||||
|
||||
Run time is <I>O(C<sup>2</sup>*R)</I>.
|
||||
|
||||
@param sort If true (default), the singular values
|
||||
are arranged so that D is sorted from largest to smallest.
|
||||
*/
|
||||
void svd(Matrix& U, Array<T>& d, Matrix& V, bool sort = true) const;
|
||||
|
||||
void set(int r, int c, T v);
|
||||
|
||||
void setCol(int c, const Matrix& vec);
|
||||
|
||||
void setRow(int r, const Matrix& vec);
|
||||
|
||||
Matrix col(int c) const;
|
||||
|
||||
Matrix row(int r) const;
|
||||
|
||||
T get(int r, int c) const;
|
||||
|
||||
Vector2int16 size() const {
|
||||
return Vector2int16(rows(), cols());
|
||||
}
|
||||
|
||||
int numElements() const {
|
||||
return rows() * cols();
|
||||
}
|
||||
|
||||
void swapRows(int r0, int r1);
|
||||
|
||||
/** Swaps columns c0 and c1 and negates both */
|
||||
void swapAndNegateCols(int c0, int c1);
|
||||
|
||||
void mulRow(int r, const T& v);
|
||||
|
||||
/** Returns true if any element is non-zero */
|
||||
bool anyNonZero() const;
|
||||
|
||||
/** Returns true if all elements are non-zero */
|
||||
bool allNonZero() const;
|
||||
|
||||
inline bool allZero() const {
|
||||
return !anyNonZero();
|
||||
}
|
||||
|
||||
inline bool anyZero() const {
|
||||
return !allNonZero();
|
||||
}
|
||||
|
||||
/** Serializes in Matlab source format */
|
||||
void serialize(TextOutput& t) const;
|
||||
|
||||
std::string toString(const std::string& name) const;
|
||||
|
||||
std::string toString() const {
|
||||
static const std::string name = "";
|
||||
return toString(name);
|
||||
}
|
||||
|
||||
/** 2-norm squared: sum(squares). (i.e., dot product with itself) */
|
||||
double normSquared() const;
|
||||
|
||||
/** 2-norm (sqrt(sum(squares)) */
|
||||
double norm() const;
|
||||
|
||||
/**
|
||||
Low-level SVD functionality. Useful for applications that do not want
|
||||
to construct a Matrix but need to perform the SVD operation.
|
||||
|
||||
this = U * D * V'
|
||||
|
||||
Assumes that rows >= cols
|
||||
|
||||
@return NULL on success, a string describing the error on failure.
|
||||
@param U rows x cols matrix to be decomposed, gets overwritten with U, a rows x cols matrix with orthogonal columns.
|
||||
@param D vector of singular values of a (diagonal of the D matrix). Length cols.
|
||||
@param V returns the right orthonormal transformation matrix, size cols x cols
|
||||
|
||||
@cite Based on Dianne Cook's implementation, which is adapted from
|
||||
svdecomp.c in XLISP-STAT 2.1, which is code from Numerical Recipes
|
||||
adapted by Luke Tierney and David Betz. The Numerical Recipes code
|
||||
is adapted from Forsythe et al, who based their code on Golub and
|
||||
Reinsch's original implementation.
|
||||
*/
|
||||
static const char* svdCore(float** U, int rows, int cols, float* D, float** V);
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator-(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M.lsub(v);
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator*(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M * v;
|
||||
}
|
||||
|
||||
inline G3D::Matrix operator+(const G3D::Matrix::T& v, const G3D::Matrix& M) {
|
||||
return M + v;
|
||||
}
|
||||
|
||||
inline G3D::Matrix abs(const G3D::Matrix& M) {
|
||||
return M.abs();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
82
dep/g3dlite/include/G3D/Matrix2.h
Normal file
82
dep/g3dlite/include/G3D/Matrix2.h
Normal file
@@ -0,0 +1,82 @@
|
||||
#ifndef G3D_Matrix2_h
|
||||
#define G3D_Matrix2_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** @beta */
|
||||
class Matrix2 {
|
||||
private:
|
||||
// Row, column
|
||||
float data[2][2];
|
||||
|
||||
public:
|
||||
|
||||
Matrix2() {
|
||||
data[0][0] = 1.0f; data[0][1] = 0.0f;
|
||||
data[1][0] = 0.0f; data[1][1] = 1.0f;
|
||||
}
|
||||
|
||||
Matrix2(float v00, float v01, float v10, float v11) {
|
||||
data[0][0] = v00; data[0][1] = v01;
|
||||
data[1][0] = v10; data[1][1] = v11;
|
||||
}
|
||||
|
||||
static Matrix2 identity() {
|
||||
return Matrix2(1.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Vector2 operator*(const Vector2& v) const {
|
||||
return Vector2(data[0][0] * v[0] + data[0][1] * v[1],
|
||||
data[1][0] * v[0] + data[1][1] * v[1]);
|
||||
}
|
||||
|
||||
Matrix2 inverse() const {
|
||||
return Matrix2(data[1][1], -data[0][1],
|
||||
-data[1][0], data[0][0]) * (1.0f / determinant());
|
||||
}
|
||||
|
||||
Matrix2 transpose() const {
|
||||
return Matrix2(data[0][0], data[1][0],
|
||||
data[0][1], data[1][1]);
|
||||
}
|
||||
|
||||
float determinant() const {
|
||||
return data[0][0] * data[1][1] - data[0][1] * data[1][0];
|
||||
}
|
||||
|
||||
Matrix2 operator*(float f) const {
|
||||
return Matrix2(data[0][0] * f, data[0][1] * f,
|
||||
data[1][0] * f, data[1][1] * f);
|
||||
}
|
||||
|
||||
Matrix2 operator/(float f) const {
|
||||
return Matrix2(data[0][0] / f, data[0][1] / f,
|
||||
data[1][0] / f, data[1][1] / f);
|
||||
}
|
||||
|
||||
inline float* operator[] (int i) {
|
||||
debugAssert(i >= 0 && i <= 1);
|
||||
return (float*)&data[i][0];
|
||||
}
|
||||
|
||||
inline const float* operator[] (int i) const {
|
||||
debugAssert(i >= 0 && i <= 1);
|
||||
return (const float*)&data[i][0];
|
||||
}
|
||||
|
||||
inline operator float* () {
|
||||
return (float*)&data[0][0];
|
||||
}
|
||||
|
||||
inline operator const float* () const{
|
||||
return (const float*)&data[0][0];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
403
dep/g3dlite/include/G3D/Matrix3.h
Normal file
403
dep/g3dlite/include/G3D/Matrix3.h
Normal file
@@ -0,0 +1,403 @@
|
||||
/**
|
||||
\file Matrix3.h
|
||||
|
||||
3x3 matrix class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\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 2011-05-05
|
||||
*/
|
||||
|
||||
#ifndef G3D_Matrix3_h
|
||||
#define G3D_Matrix3_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
A 3x3 matrix. Do not subclass. Data is unitializd when default constructed.
|
||||
*/
|
||||
class Matrix3 {
|
||||
private:
|
||||
|
||||
// Row, column
|
||||
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:
|
||||
|
||||
/** Must be in one of the following forms:
|
||||
- Matrix3(#, #, # .... #)
|
||||
- Matrix3::fromAxisAngle(#, #)
|
||||
- Matrix3::diagonal(#, #, #)
|
||||
- Matrix3::identity()
|
||||
*/
|
||||
Matrix3(const Any& any);
|
||||
|
||||
static Matrix3 fromColumns(const Vector3& c0, const Vector3& c1, const Vector3& c2) {
|
||||
Matrix3 m;
|
||||
for (int r = 0; r < 3; ++r) {
|
||||
m.elt[r][0] = c0[r];
|
||||
m.elt[r][1] = c1[r];
|
||||
m.elt[r][2] = c2[r];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
static Matrix3 fromRows(const Vector3& r0, const Vector3& r1, const Vector3& r2) {
|
||||
Matrix3 m;
|
||||
for (int c = 0; c < 3; ++c) {
|
||||
m.elt[0][c] = r0[c];
|
||||
m.elt[1][c] = r1[c];
|
||||
m.elt[2][c] = r2[c];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
/** Initial values are undefined for performance.
|
||||
\sa Matrix3::zero, Matrix3::identity, Matrix3::fromAxisAngle, etc.*/
|
||||
Matrix3() {}
|
||||
|
||||
Matrix3 (class BinaryInput& b);
|
||||
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);
|
||||
|
||||
static Matrix3 diagonal(float e00, float e11, float e22) {
|
||||
return Matrix3(e00, 0, 0,
|
||||
0, e11, 0,
|
||||
0, 0, e22);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** Returns true if column(0).cross(column(1)).dot(column(2)) > 0. */
|
||||
bool isRightHanded() const;
|
||||
|
||||
/**
|
||||
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 column(int c) const;
|
||||
const Vector3& row(int r) const;
|
||||
|
||||
void setColumn(int iCol, const Vector3 &vector);
|
||||
void setRow(int iRow, const Vector3 &vector);
|
||||
|
||||
// assignment and comparison
|
||||
inline Matrix3& operator= (const Matrix3& rkMatrix) {
|
||||
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);
|
||||
|
||||
Matrix3& operator*= (float k);
|
||||
Matrix3& operator/= (float k);
|
||||
|
||||
|
||||
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-06f) const;
|
||||
Matrix3 inverse (float fTolerance = 1e-06f) 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;
|
||||
|
||||
/**
|
||||
Polar decomposition of a matrix. Based on pseudocode from Nicholas J
|
||||
Higham, "Computing the Polar Decomposition -- with Applications Siam
|
||||
Journal of Science and Statistical Computing, Vol 7, No. 4, October
|
||||
1986.
|
||||
|
||||
Decomposes A into R*S, where R is orthogonal and S is symmetric.
|
||||
|
||||
Ken Shoemake's "Matrix animation and polar decomposition"
|
||||
in Proceedings of the conference on Graphics interface '92
|
||||
seems to be better known in the world of graphics, but Higham's version
|
||||
uses a scaling constant that can lead to faster convergence than
|
||||
Shoemake's when the initial matrix is far from orthogonal.
|
||||
*/
|
||||
void polarDecomposition(Matrix3 &R, Matrix3 &S) const;
|
||||
|
||||
/**
|
||||
* Matrix norms.
|
||||
*/
|
||||
float spectralNorm () const;
|
||||
|
||||
float squaredFrobeniusNorm() const;
|
||||
|
||||
float frobeniusNorm() const;
|
||||
|
||||
float l1Norm() const;
|
||||
|
||||
float lInfNorm() const;
|
||||
|
||||
float diffOneNorm(const Matrix3 &y) const;
|
||||
|
||||
/** matrix must be orthonormal */
|
||||
void toAxisAngle(Vector3& rkAxis, float& rfRadians) const;
|
||||
|
||||
static Matrix3 fromDiagonal(const Vector3& d) {
|
||||
return Matrix3(d.x, 0, 0,
|
||||
0, d.y, 0,
|
||||
0, 0, d.z);
|
||||
}
|
||||
|
||||
/** \sa fromUnitAxisAngle */
|
||||
static Matrix3 fromAxisAngle(const Vector3& rkAxis, float fRadians);
|
||||
|
||||
/** Assumes that rkAxis has unit length */
|
||||
static Matrix3 fromUnitAxisAngle(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 <20><><EFBFBD><EFBFBD> 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();
|
||||
|
||||
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
|
||||
|
||||
348
dep/g3dlite/include/G3D/Matrix4.h
Normal file
348
dep/g3dlite/include/G3D/Matrix4.h
Normal file
@@ -0,0 +1,348 @@
|
||||
/**
|
||||
@file Matrix4.h
|
||||
|
||||
4x4 matrix class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2003-10-02
|
||||
\edited 2012-12-25
|
||||
*/
|
||||
|
||||
#ifndef G3D_Matrix4_h
|
||||
#define G3D_Matrix4_h
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Disable conditional expression is constant, which occurs incorrectly on inlined functions
|
||||
# pragma warning (push)
|
||||
# pragma warning( disable : 4127 )
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Vector3.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
class Matrix2;
|
||||
|
||||
/**
|
||||
A 4x4 matrix. Do not subclass. Data is initialized to 0 when default constructed.
|
||||
|
||||
\sa G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat
|
||||
*/
|
||||
class Matrix4 {
|
||||
private:
|
||||
|
||||
float elt[4][4];
|
||||
|
||||
/**
|
||||
Computes the determinant of the 3x3 matrix that lacks excludeRow
|
||||
and excludeCol.
|
||||
*/
|
||||
float subDeterminant(int excludeRow, int excludeCol) const;
|
||||
|
||||
// Hidden operators
|
||||
bool operator<(const Matrix4&) const;
|
||||
bool operator>(const Matrix4&) const;
|
||||
bool operator<=(const Matrix4&) const;
|
||||
bool operator>=(const Matrix4&) const;
|
||||
|
||||
public:
|
||||
|
||||
/** Must be in one of the following forms:
|
||||
- Matrix4(#, #, # .... #)
|
||||
- Matrix4::scale(#)
|
||||
- Matrix4::scale(#, #, #)
|
||||
- Matrix4::translation(#, #, #)
|
||||
- Matrix4::identity()
|
||||
- Matrix4::rollDegrees(#)
|
||||
- Matrix4::pitchDegrees(#)
|
||||
- Matrix4::yawDegrees(#)
|
||||
*/
|
||||
explicit Matrix4(const Any& any);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
Matrix4(
|
||||
float r1c1, float r1c2, float r1c3, float r1c4,
|
||||
float r2c1, float r2c2, float r2c3, float r2c4,
|
||||
float r3c1, float r3c2, float r3c3, float r3c4,
|
||||
float r4c1, float r4c2, float r4c3, float r4c4);
|
||||
|
||||
/**
|
||||
init should be <B>row major</B>.
|
||||
*/
|
||||
Matrix4(const float* init);
|
||||
|
||||
/**
|
||||
a is the upper left 3x3 submatrix and b is the upper right 3x1 submatrix. The last row of the created matrix is (0,0,0,1).
|
||||
*/
|
||||
Matrix4(const class Matrix3& upper3x3, const class Vector3& lastCol = Vector3::zero());
|
||||
|
||||
Matrix4(const class CoordinateFrame& c);
|
||||
|
||||
Matrix4(const double* init);
|
||||
|
||||
/** Matrix4::zero() */
|
||||
Matrix4();
|
||||
|
||||
static Matrix4 diagonal(float e00, float e11, float e22, float e33) {
|
||||
return Matrix4(e00, 0, 0, 0,
|
||||
0, e11, 0, 0,
|
||||
0, 0, e22, 0,
|
||||
0, 0, 0, e33);
|
||||
}
|
||||
|
||||
/** Produces an RT transformation that nearly matches this Matrix4.
|
||||
Because a Matrix4 may not be precisely a rotation and translation,
|
||||
this may introduce error. */
|
||||
class CoordinateFrame approxCoordinateFrame() const;
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Matrix4& identity();
|
||||
static const Matrix4& zero();
|
||||
|
||||
/** If this is a perspective projection matrix created by
|
||||
Matrix4::perspectiveProjection, extract its parameters.
|
||||
|
||||
Uses double precision because the operations involved in
|
||||
projection involve divisions that can significantly impact
|
||||
precision.
|
||||
*/
|
||||
void getPerspectiveProjectionParameters
|
||||
(double& left,
|
||||
double& right,
|
||||
double& bottom,
|
||||
double& top,
|
||||
double& nearval,
|
||||
double& farval,
|
||||
float updirection = -1.0f) const;
|
||||
|
||||
inline float* operator[](int r) {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (float*)&elt[r];
|
||||
}
|
||||
|
||||
inline const float* operator[](int r) const {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (const float*)&elt[r];
|
||||
}
|
||||
|
||||
/** Returns a row-major pointer. */
|
||||
inline operator float* () {
|
||||
return (float*)&elt[0][0];
|
||||
}
|
||||
|
||||
inline operator const float* () const {
|
||||
return (const float*)&elt[0][0];
|
||||
}
|
||||
|
||||
Matrix4 operator*(const Matrix4& other) const;
|
||||
Matrix4 operator+(const Matrix4& other) const {
|
||||
Matrix4 result;
|
||||
for (int r = 0; r < 4; ++r) {
|
||||
for (int c = 0; c < 4; ++c) {
|
||||
result.elt[r][c] = elt[r][c] + other.elt[r][c];
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
class Matrix3 upper3x3() const;
|
||||
|
||||
class Matrix2 upper2x2() const;
|
||||
|
||||
/** Homogeneous multiplication. Let k = M * [v w]^T. result = k.xyz() / k.w */
|
||||
class Vector3 homoMul(const class Vector3& v, float w) const;
|
||||
|
||||
/**
|
||||
Constructs an orthogonal projection matrix from the given parameters.
|
||||
Near and far are the <b>NEGATIVE</b> of the near and far plane Z values
|
||||
(to follow OpenGL conventions).
|
||||
|
||||
\param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
*/
|
||||
static Matrix4 orthogonalProjection(
|
||||
float left,
|
||||
float right,
|
||||
float bottom,
|
||||
float top,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
*/
|
||||
static Matrix4 orthogonalProjection(
|
||||
const class Rect2D& rect,
|
||||
float nearval,
|
||||
float farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
/** \param upDirection Use -1.0 for 2D Y increasing downwards (the G3D 8.x default convention),
|
||||
1.0 for 2D Y increasing upwards (the G3D 7.x default and OpenGL convention)
|
||||
|
||||
Uses double precision because the operations involved in
|
||||
projection involve divisions that can significantly impact
|
||||
precision. */
|
||||
static Matrix4 perspectiveProjection(
|
||||
double left,
|
||||
double right,
|
||||
double bottom,
|
||||
double top,
|
||||
double nearval,
|
||||
double farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
void setRow(int r, const class Vector4& v);
|
||||
void setColumn(int c, const Vector4& v);
|
||||
|
||||
const Vector4& row(int r) const;
|
||||
Vector4 column(int c) const;
|
||||
|
||||
Matrix4 operator*(const float s) const;
|
||||
Vector4 operator*(const Vector4& vector) const;
|
||||
|
||||
Matrix4 transpose() const;
|
||||
|
||||
bool operator!=(const Matrix4& other) const;
|
||||
bool operator==(const Matrix4& other) const;
|
||||
|
||||
float determinant() const;
|
||||
Matrix4 inverse() const;
|
||||
|
||||
/**
|
||||
Transpose of the cofactor matrix (used in computing the inverse).
|
||||
Note: This is in fact only one type of adjoint. More generally,
|
||||
an adjoint of a matrix is any mapping of a matrix which possesses
|
||||
certain properties. This returns the so-called adjugate
|
||||
or classical adjoint.
|
||||
*/
|
||||
Matrix4 adjoint() const;
|
||||
Matrix4 cofactor() const;
|
||||
|
||||
/** Serializes row-major */
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
std::string toString() const;
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(const Vector3& v) {
|
||||
return Matrix4(v.x, 0, 0, 0,
|
||||
0, v.y, 0, 0,
|
||||
0, 0, v.z, 0,
|
||||
0, 0, 0, 1);
|
||||
}
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(float x, float y, float z) {
|
||||
return scale(Vector3(x, y, z));
|
||||
}
|
||||
|
||||
/** 3D scale matrix */
|
||||
inline static Matrix4 scale(float s) {
|
||||
return scale(s,s,s);
|
||||
}
|
||||
|
||||
/** 3D translation matrix */
|
||||
inline static Matrix4 translation(const Vector3& v) {
|
||||
return Matrix4(Matrix3::identity(), v);
|
||||
}
|
||||
|
||||
inline static Matrix4 translation(float x, float y, float z) {
|
||||
return Matrix4(Matrix3::identity(), Vector3(x, y, z));
|
||||
}
|
||||
|
||||
/** Create a rotation matrix that rotates \a deg degrees around the Y axis */
|
||||
inline static Matrix4 yawDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitY(), toRadians(deg)));
|
||||
}
|
||||
|
||||
inline static Matrix4 pitchDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitX(), toRadians(deg)));
|
||||
}
|
||||
|
||||
inline static Matrix4 rollDegrees(float deg) {
|
||||
return Matrix4(Matrix3::fromAxisAngle(Vector3::unitZ(), toRadians(deg)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Double-precision 4x4 matrix */
|
||||
class Matrix4float64 {
|
||||
private:
|
||||
|
||||
double elt[4][4];
|
||||
|
||||
public:
|
||||
|
||||
explicit Matrix4float64(const Matrix4& m);
|
||||
|
||||
/** all zeros */
|
||||
Matrix4float64();
|
||||
|
||||
Matrix4float64(
|
||||
double r1c1, double r1c2, double r1c3, double r1c4,
|
||||
double r2c1, double r2c2, double r2c3, double r2c4,
|
||||
double r3c1, double r3c2, double r3c3, double r3c4,
|
||||
double r4c1, double r4c2, double r4c3, double r4c4);
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Matrix4float64& identity();
|
||||
|
||||
static const Matrix4float64& zero();
|
||||
|
||||
bool operator!=(const Matrix4float64& other) const;
|
||||
|
||||
bool operator==(const Matrix4float64& other) const;
|
||||
|
||||
Vector4 operator*(const Vector4& vector) const;
|
||||
|
||||
static Matrix4float64 perspectiveProjection(
|
||||
double left,
|
||||
double right,
|
||||
double bottom,
|
||||
double top,
|
||||
double nearval,
|
||||
double farval,
|
||||
float upDirection = -1.0f);
|
||||
|
||||
inline double* operator[](int r) {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (double*)&elt[r];
|
||||
}
|
||||
|
||||
inline const double* operator[](int r) const {
|
||||
debugAssert(r >= 0);
|
||||
debugAssert(r < 4);
|
||||
return (const double*)&elt[r];
|
||||
}
|
||||
|
||||
inline operator double* () {
|
||||
return (double*)&elt[0][0];
|
||||
}
|
||||
|
||||
inline operator const double* () const {
|
||||
return (const double*)&elt[0][0];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# pragma warning (pop)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
94
dep/g3dlite/include/G3D/MemoryManager.h
Normal file
94
dep/g3dlite/include/G3D/MemoryManager.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
@file MemoryManager.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2009-04-20
|
||||
@edited 2009-04-20
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_MemoryManager_h
|
||||
#define G3D_MemoryManager_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Abstraction of memory management.
|
||||
Default implementation uses G3D::System::malloc and is threadsafe.
|
||||
|
||||
\sa LargePoolMemoryManager, CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
|
||||
class MemoryManager : public ReferenceCountedObject {
|
||||
protected:
|
||||
|
||||
MemoryManager();
|
||||
|
||||
public:
|
||||
|
||||
typedef shared_ptr<class MemoryManager> Ref;
|
||||
|
||||
/** Return a pointer to \a s bytes of memory that are unused by
|
||||
the rest of the program. The contents of the memory are
|
||||
undefined */
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
/** Invoke to declare that this memory will no longer be used by
|
||||
the program. The memory manager is not required to actually
|
||||
reuse or release this memory. */
|
||||
virtual void free(void* ptr);
|
||||
|
||||
/** Returns true if this memory manager is threadsafe (i.e., alloc
|
||||
and free can be called asychronously) */
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** Return the instance. There's only one instance of the default
|
||||
MemoryManager; it is cached after the first creation. */
|
||||
static MemoryManager::Ref create();
|
||||
};
|
||||
|
||||
/**
|
||||
Allocates memory on 16-byte boundaries.
|
||||
\sa MemoryManager, CRTMemoryManager, AreaMemoryManager */
|
||||
class AlignedMemoryManager : public MemoryManager {
|
||||
protected:
|
||||
|
||||
AlignedMemoryManager();
|
||||
|
||||
public:
|
||||
|
||||
typedef shared_ptr<class AlignedMemoryManager> Ref;
|
||||
|
||||
|
||||
virtual void* alloc(size_t s);
|
||||
|
||||
virtual void free(void* ptr);
|
||||
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
static AlignedMemoryManager::Ref create();
|
||||
};
|
||||
|
||||
|
||||
/** A MemoryManager implemented using the C runtime. Not recommended
|
||||
for general use; this is largely for debugging. */
|
||||
class CRTMemoryManager : public MemoryManager {
|
||||
protected:
|
||||
CRTMemoryManager();
|
||||
|
||||
public:
|
||||
typedef shared_ptr<class MemoryManager> Ref;
|
||||
virtual void* alloc(size_t s);
|
||||
virtual void free(void* ptr);
|
||||
virtual bool isThreadsafe() const;
|
||||
|
||||
/** There's only one instance of this memory manager; it is
|
||||
cached after the first creation. */
|
||||
static CRTMemoryManager::Ref create();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
690
dep/g3dlite/include/G3D/MeshAlg.h
Normal file
690
dep/g3dlite/include/G3D/MeshAlg.h
Normal file
@@ -0,0 +1,690 @@
|
||||
/**
|
||||
@file MeshAlg.h
|
||||
|
||||
Indexed Mesh algorithms.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2003-09-14
|
||||
@edited 2010-01-18
|
||||
*/
|
||||
|
||||
#ifndef G3D_MeshAlg_h
|
||||
#define G3D_MeshAlg_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include "G3D/SmallArray.h"
|
||||
#include "G3D/constants.h"
|
||||
#include "G3D/Image1.h"
|
||||
|
||||
#ifdef G3D_WINDOWS
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
#pragma warning( push )
|
||||
#pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Indexed <B>mesh alg</B>orithms. You have to build your own mesh class.
|
||||
<P>
|
||||
No mesh class is provided with G3D because there isn't an "ideal"
|
||||
mesh format-- one application needs keyframed animation, another
|
||||
skeletal animation, a third texture coordinates, a fourth
|
||||
cannot precompute information, etc. Instead of compromising, this
|
||||
class implements the hard parts of mesh computation and you can write
|
||||
your own ideal mesh class on top of it.
|
||||
|
||||
\sa G3D::ArticulatedModel, G3D::IFSModel
|
||||
*/
|
||||
class MeshAlg {
|
||||
public:
|
||||
|
||||
/** \deprecated */
|
||||
typedef PrimitiveType Primitive;
|
||||
|
||||
/** Adjacency information for a vertex.
|
||||
Does not contain the vertex position or normal,
|
||||
which are stored in the MeshAlg::Geometry object.
|
||||
<CODE>Vertex</CODE>s must be stored in an array
|
||||
parallel to (indexed in the same way as)
|
||||
MeshAlg::Geometry::vertexArray.
|
||||
*/
|
||||
class Vertex {
|
||||
public:
|
||||
Vertex() {}
|
||||
|
||||
/**
|
||||
Array of edges adjacent to this vertex.
|
||||
Let e = edgeIndex[i].
|
||||
edge[(e >= 0) ? e : ~e].vertexIndex[0] == this
|
||||
vertex index.
|
||||
|
||||
Edges may be listed multiple times if they are
|
||||
degenerate.
|
||||
*/
|
||||
SmallArray<int, 6> edgeIndex;
|
||||
|
||||
/**
|
||||
Returns true if e or ~e is in the edgeIndex list.
|
||||
*/
|
||||
inline bool inEdge(int e) const {
|
||||
return edgeIndex.contains(~e) || edgeIndex.contains(e);
|
||||
}
|
||||
|
||||
/**
|
||||
Array of faces containing this vertex. Faces
|
||||
may be listed multiple times if they are degenerate.
|
||||
*/
|
||||
SmallArray<int, 6> faceIndex;
|
||||
|
||||
inline bool inFace(int f) const {
|
||||
debugAssert(f >= 0);
|
||||
return faceIndex.contains(f);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Oriented, indexed triangle.
|
||||
*/
|
||||
class Face {
|
||||
public:
|
||||
Face();
|
||||
|
||||
/**
|
||||
Used by Edge::faceIndex to indicate a missing face.
|
||||
This is a large negative value.
|
||||
*/
|
||||
static const int NONE;
|
||||
|
||||
|
||||
/**
|
||||
Vertices in the face in counter-clockwise order.
|
||||
Degenerate faces may include the same vertex multiple times.
|
||||
*/
|
||||
int vertexIndex[3];
|
||||
|
||||
inline bool containsVertex(int v) const {
|
||||
return contains(vertexIndex, 3, v);
|
||||
}
|
||||
|
||||
/**
|
||||
Edge indices in counter-clockwise order. Edges are
|
||||
undirected, so it is important to know which way
|
||||
each edge is pointing in a face. This is encoded
|
||||
using negative indices.
|
||||
|
||||
If <CODE>edgeIndex[i] >= 0</CODE> then this face
|
||||
contains the directed edge
|
||||
between vertex indices
|
||||
<CODE>edgeArray[face.edgeIndex[i]].vertexIndex[0]</CODE>
|
||||
and
|
||||
<CODE>edgeArray[face.edgeIndex[i]].vertexIndex[1]</CODE>.
|
||||
|
||||
If <CODE>edgeIndex[i] < 0</CODE> then
|
||||
<CODE>~edgeIndex[i]</CODE> (i.e. the two's
|
||||
complement of) is used and this face contains the directed
|
||||
edge between vertex indices
|
||||
<CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[0]</CODE>
|
||||
and
|
||||
<CODE>edgeArray[~face.edgeIndex[i]].vertexIndex[1]</CODE>.
|
||||
|
||||
Degenerate faces may include the same edge multiple times.
|
||||
*/
|
||||
// Temporarily takes on the value Face::NONE during adjacency
|
||||
// computation to indicate an edge that has not yet been assigned.
|
||||
int edgeIndex[3];
|
||||
|
||||
inline bool containsEdge(int e) const {
|
||||
if (e < 0) {
|
||||
e = ~e;
|
||||
}
|
||||
return contains(edgeIndex, 3, e) || contains(edgeIndex, 3, ~e);
|
||||
}
|
||||
|
||||
/** Contains the forward edge e if e >= 0 and the backward edge
|
||||
~e otherwise. */
|
||||
inline bool containsDirectedEdge(int e) const {
|
||||
return contains(edgeIndex, 3, e);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/** Oriented, indexed edge */
|
||||
class Edge {
|
||||
public:
|
||||
Edge();
|
||||
|
||||
/** Degenerate edges may include the same vertex times. */
|
||||
int vertexIndex[2];
|
||||
|
||||
inline bool containsVertex(int v) const {
|
||||
return contains(vertexIndex, 2, v);
|
||||
}
|
||||
|
||||
/**
|
||||
The edge is directed <B>forward</B> in face 0
|
||||
<B>backward</B> in face 1. Face index of MeshAlg::Face::NONE
|
||||
indicates a boundary (a.k.a. crack, broken) edge.
|
||||
*/
|
||||
int faceIndex[2];
|
||||
|
||||
/** Returns true if f is contained in the faceIndex array in either slot.
|
||||
To see if it is forward in that face, just check edge.faceIndex[0] == f.*/
|
||||
inline bool inFace(int f) const {
|
||||
return contains(faceIndex, 2, f);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if either faceIndex is NONE.
|
||||
*/
|
||||
inline bool boundary() const {
|
||||
return (faceIndex[0] == Face::NONE) ||
|
||||
(faceIndex[1] == Face::NONE);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the reversed edge.
|
||||
*/
|
||||
inline Edge reverse() const {
|
||||
Edge e;
|
||||
e.vertexIndex[0] = vertexIndex[1];
|
||||
e.vertexIndex[1] = vertexIndex[0];
|
||||
e.faceIndex[0] = faceIndex[1];
|
||||
e.faceIndex[1] = faceIndex[0];
|
||||
return e;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Convenient for passing around the per-vertex data that changes under
|
||||
animation. The faces and edges are needed to interpret
|
||||
these values.
|
||||
*/
|
||||
class Geometry {
|
||||
public:
|
||||
/** Vertex positions */
|
||||
Array<Vector3> vertexArray;
|
||||
|
||||
/** Vertex normals */
|
||||
Array<Vector3> normalArray;
|
||||
|
||||
/**
|
||||
Assignment is optimized using SSE.
|
||||
*/
|
||||
Geometry& operator=(const Geometry& src);
|
||||
|
||||
void clear() {
|
||||
vertexArray.clear();
|
||||
normalArray.clear();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Given a set of vertices and a set of indices for traversing them
|
||||
to create triangles, computes other mesh properties.
|
||||
|
||||
<B>Colocated vertices are treated as separate.</B> To have
|
||||
colocated vertices collapsed (necessary for many algorithms,
|
||||
like shadowing), weld the mesh before computing adjacency.
|
||||
|
||||
<I>Recent change: In version 6.00, colocated vertices were automatically
|
||||
welded by this routine and degenerate faces and edges were removed. That
|
||||
is no longer the case.</I>
|
||||
|
||||
Where two faces meet, there are two opposite directed edges. These
|
||||
are collapsed into a single bidirectional edge in the edgeArray.
|
||||
If four faces meet exactly at the same edge, that edge will appear
|
||||
twice in the array, and so on. If an edge is a boundary of the mesh
|
||||
(i.e. if the edge has only one adjacent face) it will appear in the
|
||||
array with one face index set to MeshAlg::Face::NONE.
|
||||
|
||||
@param vertexGeometry %Vertex positions to use when deciding colocation.
|
||||
@param indexArray Order to traverse vertices to make triangles
|
||||
@param faceArray <I>Output</I>
|
||||
@param edgeArray <I>Output</I>. Sorted so that boundary edges are at the end of the array.
|
||||
@param vertexArray <I>Output</I>
|
||||
*/
|
||||
static void computeAdjacency(
|
||||
const Array<Vector3>& vertexGeometry,
|
||||
const Array<int>& indexArray,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray);
|
||||
|
||||
/**
|
||||
@deprecated Use the other version of computeAdjacency, which takes Array<Vertex>.
|
||||
@param facesAdjacentToVertex <I>Output</I> adjacentFaceArray[v] is an array of
|
||||
indices for faces touching vertex index v
|
||||
*/
|
||||
static void computeAdjacency(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<int>& indexArray,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array< Array<int> >& facesAdjacentToVertex);
|
||||
|
||||
/**
|
||||
Computes some basic mesh statistics including: min, max mean and median,
|
||||
edge lengths; and min, mean, median, and max face area.
|
||||
|
||||
@param vertexArray %Vertex positions to use when deciding colocation.
|
||||
@param indexArray Order to traverse vertices to make triangles
|
||||
@param minEdgeLength Minimum edge length
|
||||
@param meanEdgeLength Mean edge length
|
||||
@param medianEdgeLength Median edge length
|
||||
@param maxEdgeLength Max edge length
|
||||
@param minFaceArea Minimum face area
|
||||
@param meanFaceArea Mean face area
|
||||
@param medianFaceArea Median face area
|
||||
@param maxFaceArea Max face area
|
||||
*/
|
||||
static void computeAreaStatistics(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<int>& indexArray,
|
||||
double& minEdgeLength,
|
||||
double& meanEdgeLength,
|
||||
double& medianEdgeLength,
|
||||
double& maxEdgeLength,
|
||||
double& minFaceArea,
|
||||
double& meanFaceArea,
|
||||
double& medianFaceArea,
|
||||
double& maxFaceArea);
|
||||
|
||||
private:
|
||||
|
||||
/** Helper for weldAdjacency */
|
||||
static void weldBoundaryEdges(
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray);
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Computes tangent and binormal vectors,
|
||||
which provide a (mostly) consistent
|
||||
parameterization over the surface for
|
||||
effects like bump mapping. In the resulting coordinate frame,
|
||||
T = x (varies with texture s coordinate), B = y (varies with negative texture t coordinate),
|
||||
and N = z for a right-handed coordinate frame. If a billboard is vertical on the screen
|
||||
in view of the camera, the tangent space matches the camera's coordinate frame.
|
||||
|
||||
The vertex, texCoord, tangent, and binormal
|
||||
arrays are parallel arrays.
|
||||
|
||||
The resulting tangent and binormal might not be exactly
|
||||
perpendicular to each other. They are guaranteed to
|
||||
be perpendicular to the normal.
|
||||
|
||||
@cite Max McGuire
|
||||
*/
|
||||
static void computeTangentSpaceBasis(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Vector2>& texCoordArray,
|
||||
const Array<Vector3>& vertexNormalArray,
|
||||
const Array<Face>& faceArray,
|
||||
Array<Vector3>& tangent,
|
||||
Array<Vector3>& binormal);
|
||||
|
||||
/** @deprecated */
|
||||
static void computeNormals(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Array< Array<int> >& adjacentFaceArray,
|
||||
Array<Vector3>& vertexNormalArray,
|
||||
Array<Vector3>& faceNormalArray);
|
||||
|
||||
/**
|
||||
Vertex normals are weighted by the area of adjacent faces.
|
||||
Nelson Max showed this is superior to uniform weighting for
|
||||
general meshes in jgt.
|
||||
|
||||
@param vertexNormalArray Output. Unit length
|
||||
@param faceNormalArray Output. Degenerate faces produce zero magnitude normals. Unit length
|
||||
@see weld
|
||||
*/
|
||||
static void computeNormals(
|
||||
const Array<Vector3>& vertexGeometry,
|
||||
const Array<Face>& faceArray,
|
||||
const Array<Vertex>& vertexArray,
|
||||
Array<Vector3>& vertexNormalArray,
|
||||
Array<Vector3>& faceNormalArray);
|
||||
|
||||
/** Computes unit length normals in place using the other computeNormals methods.
|
||||
If you already have a face array use another method; it will be faster.
|
||||
@see weld*/
|
||||
static void computeNormals(
|
||||
Geometry& geometry,
|
||||
const Array<int>& indexArray);
|
||||
|
||||
/**
|
||||
Computes face normals only. Significantly faster (especially if
|
||||
normalize is false) than computeNormals.
|
||||
@see weld
|
||||
*/
|
||||
static void computeFaceNormals(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
Array<Vector3>& faceNormals,
|
||||
bool normalize = true);
|
||||
|
||||
/**
|
||||
Classifies each face as a backface or a front face relative
|
||||
to the observer point P (which is at infinity when P.w = 0).
|
||||
A face with normal exactly perpendicular to the observer vector
|
||||
may be classified as either a front or a back face arbitrarily.
|
||||
*/
|
||||
static void identifyBackfaces(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Vector4& P,
|
||||
Array<bool>& backface);
|
||||
|
||||
/** A faster version of identifyBackfaces for the case where
|
||||
face normals have already been computed */
|
||||
static void identifyBackfaces(
|
||||
const Array<Vector3>& vertexArray,
|
||||
const Array<Face>& faceArray,
|
||||
const Vector4& P,
|
||||
Array<bool>& backface,
|
||||
const Array<Vector3>& faceNormals);
|
||||
|
||||
/**
|
||||
Welds nearby and colocated elements of the <I>oldVertexArray</I> together so that
|
||||
<I>newVertexArray</I> contains no vertices within <I>radius</I> of one another.
|
||||
Every vertex in newVertexPositions also appears in oldVertexPositions.
|
||||
This is useful for downsampling meshes and welding cracks created by artist errors
|
||||
or numerical imprecision.
|
||||
|
||||
The two integer arrays map indices back and forth between the arrays according to:
|
||||
<PRE>
|
||||
oldVertexArray[toOld[ni]] == newVertexArray[ni]
|
||||
oldVertexArray[oi] == newVertexArray[toNew[ni]]
|
||||
</PRE>
|
||||
|
||||
Note that newVertexPositions is never longer than oldVertexPositions
|
||||
and is shorter when vertices are welded.
|
||||
|
||||
Welding with a large radius will effectively compute a lower level of detail for
|
||||
the mesh.
|
||||
|
||||
The welding method runs in roughly linear time in the length of oldVertexArray--
|
||||
a uniform spatial grid is used to achieve nearly constant time vertex collapses
|
||||
for uniformly distributed vertices.
|
||||
|
||||
It is sometimes desirable to keep the original vertex ordering but
|
||||
identify the unique vertices. The following code computes
|
||||
array canonical s.t. canonical[v] = first occurance of
|
||||
a vertex near oldVertexPositions[v] in oldVertexPositions.
|
||||
|
||||
<PRE>
|
||||
Array<int> canonical(oldVertexPositions.size()), toNew, toOld;
|
||||
computeWeld(oldVertexPositions, Array<Vector3>(), toNew, toOld, radius);
|
||||
for (int v = 0; v < canonical.size(); ++v) {
|
||||
canonical[v] = toOld[toNew[v]];
|
||||
}
|
||||
</PRE>
|
||||
|
||||
See also G3D::MeshAlg::weldAdjacency.
|
||||
|
||||
@cite The method is that described as the 'Grouper' in Baum, Mann, Smith, and Winget,
|
||||
Making Radiosity Usable: Automatic Preprocessing and Meshing Techniques for
|
||||
the Generation of Accurate Radiosity Solutions, Computer Graphics vol 25, no 4, July 1991.
|
||||
|
||||
@deprecated Use weld.
|
||||
*/
|
||||
static void computeWeld(
|
||||
const Array<Vector3>& oldVertexPositions,
|
||||
Array<Vector3>& newVertexPositions,
|
||||
Array<int>& toNew,
|
||||
Array<int>& toOld,
|
||||
float radius = fuzzyEpsilon32);
|
||||
|
||||
/**
|
||||
Modifies the face, edge, and vertex arrays in place so that
|
||||
colocated (within radius) vertices are treated as identical.
|
||||
Note that the vertexArray and corresponding geometry will
|
||||
contain elements that are no longer used. In the vertexArray,
|
||||
these elements are initialized to MeshAlg::Vertex() but not
|
||||
removed (because removal would change the indexing).
|
||||
|
||||
This is a good preprocessing step for algorithms that are only
|
||||
concerned with the shape of a mesh (e.g. cartoon rendering, fur, shadows)
|
||||
and not the indexing of the vertices.
|
||||
|
||||
Use this method when you have already computed adjacency information
|
||||
and want to collapse colocated vertices within that data without
|
||||
disturbing the actual mesh vertices or indexing scheme.
|
||||
|
||||
If you have not computed adjacency already, use MeshAlg::computeWeld
|
||||
instead and compute adjacency information after welding.
|
||||
|
||||
@deprecated Use weld.
|
||||
|
||||
@param faceArray Mutated in place. Size is maintained (degenerate
|
||||
faces are <b>not</B> removed).
|
||||
@param edgeArray Mutated in place. May shrink if boundary edges
|
||||
are welded together.
|
||||
@param vertexArray Mutated in place. Size is maintained (duplicate
|
||||
vertices contain no adjacency info).
|
||||
*/
|
||||
static void weldAdjacency(
|
||||
const Array<Vector3>& originalGeometry,
|
||||
Array<Face>& faceArray,
|
||||
Array<Edge>& edgeArray,
|
||||
Array<Vertex>& vertexArray,
|
||||
float radius = fuzzyEpsilon32);
|
||||
|
||||
|
||||
/**
|
||||
Counts the number of edges (in an edge array returned from
|
||||
MeshAlg::computeAdjacency) that have only one adjacent face.
|
||||
*/
|
||||
static int countBoundaryEdges(const Array<Edge>& edgeArray);
|
||||
|
||||
|
||||
/**
|
||||
Generates an array of integers from start to start + n - 1 that have run numbers
|
||||
in series then omit the next skip before the next run. Useful for turning
|
||||
a triangle list into an indexed face set.
|
||||
|
||||
Example:
|
||||
<PRE>
|
||||
createIndexArray(10, x);
|
||||
// x = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
|
||||
|
||||
createIndexArray(5, x, 2);
|
||||
// x = [2, 3, 4, 5, 6, 7]
|
||||
|
||||
createIndexArray(6, x, 0, 2, 1);
|
||||
// x = [0, 1, 3, 4, 6, 7]
|
||||
</PRE>
|
||||
*/
|
||||
static void createIndexArray(
|
||||
int n,
|
||||
Array<int>& array,
|
||||
int start = 0,
|
||||
int run = 1,
|
||||
int skip = 0);
|
||||
|
||||
/**
|
||||
Computes a conservative, near-optimal axis aligned bounding box and sphere.
|
||||
|
||||
@cite The bounding sphere uses the method from J. Ritter. An effcient bounding sphere. In Andrew S. Glassner, editor, Graphics Gems. Academic Press, Boston, MA, 1990.
|
||||
|
||||
*/
|
||||
static void computeBounds(const Array<Vector3>& vertex, class AABox& box, class Sphere& sphere);
|
||||
|
||||
/** Computes bounds for a subset of the vertices. It is ok if vertices appear more than once in the index array. */
|
||||
static void computeBounds(const Array<Vector3>& vertex, const Array<int>& index, class AABox& box, class Sphere& sphere);
|
||||
|
||||
/**
|
||||
In debug mode, asserts that the adjacency references between the
|
||||
face, edge, and vertex array are consistent.
|
||||
*/
|
||||
static void debugCheckConsistency(
|
||||
const Array<Face>& faceArray,
|
||||
const Array<Edge>& edgeArray,
|
||||
const Array<Vertex>& vertexArray);
|
||||
|
||||
/**
|
||||
Generates a unit square in the X-Z plane composed of a grid of wCells x hCells
|
||||
squares on the unit interval and then transforms it by xform.
|
||||
|
||||
@param vertex Output vertices
|
||||
@param texCoord Output texture coordinates
|
||||
@param index Output triangle list indices
|
||||
@param textureScale Lower-right texture coordinate
|
||||
@param spaceCentered If true, the coordinates generated are centered at the origin before the transformation.
|
||||
@param twoSided If true, matching top and bottom planes are generated.
|
||||
\param elevation If non-NULL, values from this image are used as elevations. Apply an \a xform to adjust the scale
|
||||
*/
|
||||
static void generateGrid
|
||||
(Array<Vector3>& vertex,
|
||||
Array<Vector2>& texCoord,
|
||||
Array<int>& index,
|
||||
int wCells = 10,
|
||||
int hCells = 10,
|
||||
const Vector2& textureScale = Vector2(1,1),
|
||||
bool spaceCentered = true,
|
||||
bool twoSided = true,
|
||||
const CoordinateFrame& xform = CoordinateFrame(),
|
||||
const Image1::Ref& elevation = Image1::Ref());
|
||||
|
||||
/** Converts quadlist (QUADS),
|
||||
triangle fan (TRIANGLE_FAN),
|
||||
tristrip(TRIANGLE_STRIP), and quadstrip (QUAD_STRIP) indices into
|
||||
triangle list (TRIANGLES) indices and appends them to outIndices. */
|
||||
template<class IndexType>
|
||||
static void toIndexedTriList(
|
||||
const Array<IndexType>& inIndices,
|
||||
MeshAlg::Primitive inType,
|
||||
Array<IndexType>& outIndices) {
|
||||
|
||||
debugAssert(
|
||||
inType == PrimitiveType::TRIANGLE_STRIP ||
|
||||
inType == PrimitiveType::TRIANGLE_FAN ||
|
||||
inType == PrimitiveType::QUADS ||
|
||||
inType == PrimitiveType::QUAD_STRIP);
|
||||
|
||||
const int inSize = inIndices.size();
|
||||
|
||||
switch(inType) {
|
||||
case PrimitiveType::TRIANGLE_FAN:
|
||||
{
|
||||
debugAssert(inSize >= 3);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
for (IndexType i = 1, outIndex = N; i <= (inSize - 2); ++i, outIndex += 3) {
|
||||
outIndices[outIndex] = inIndices[0];
|
||||
outIndices[outIndex + 1] = inIndices[i];
|
||||
outIndices[outIndex + 2] = inIndices[i + 1];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::TRIANGLE_STRIP:
|
||||
{
|
||||
debugAssert(inSize >= 3);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
bool atEven = false;
|
||||
for (IndexType i = 0, outIndex = N; i < (inSize - 2); ++i, outIndex += 3) {
|
||||
if (atEven) {
|
||||
outIndices[outIndex] = inIndices[i + 1];
|
||||
outIndices[outIndex + 1] = inIndices[i];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
atEven = false;
|
||||
} else {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
atEven = true;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::QUADS:
|
||||
{
|
||||
debugAssert(inIndices.size() >= 4);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize / 4) * 3);
|
||||
|
||||
for (IndexType i = 0, outIndex = N; i <= (inSize - 4); i += 4, outIndex += 6) {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 3];
|
||||
outIndices[outIndex + 3] = inIndices[i + 1];
|
||||
outIndices[outIndex + 4] = inIndices[i + 2];
|
||||
outIndices[outIndex + 5] = inIndices[i + 3];
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case PrimitiveType::QUAD_STRIP:
|
||||
{
|
||||
debugAssert(inIndices.size() >= 4);
|
||||
|
||||
int N = outIndices.size();
|
||||
outIndices.resize(N + (inSize - 2) * 3);
|
||||
|
||||
for (IndexType i = 0, outIndex = N; i <= (inSize - 2); i += 2, outIndex += 6) {
|
||||
outIndices[outIndex] = inIndices[i];
|
||||
outIndices[outIndex + 1] = inIndices[i + 1];
|
||||
outIndices[outIndex + 2] = inIndices[i + 2];
|
||||
outIndices[outIndex + 3] = inIndices[i + 2];
|
||||
outIndices[outIndex + 4] = inIndices[i + 1];
|
||||
outIndices[outIndex + 5] = inIndices[i + 3];
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
alwaysAssertM(false, "Illegal argument");
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/**
|
||||
Helper for computeAdjacency. If a directed edge with index e already
|
||||
exists from i0 to i1 then e is returned. If a directed edge with index e
|
||||
already exists from i1 to i0, ~e is returned (the complement) and
|
||||
edgeArray[e] is set to f. Otherwise, a new edge is created from i0 to i1
|
||||
with first face index f and its index is returned.
|
||||
|
||||
@param vertexArray Vertex positions to use when deciding colocation.
|
||||
|
||||
@param area Area of face f. When multiple edges of the same direction
|
||||
are found between the same vertices (usually because of degenerate edges)
|
||||
the face with larger area is kept in the edge table.
|
||||
*/
|
||||
static int findEdgeIndex(
|
||||
const Array<Vector3>& vertexArray,
|
||||
Array<Edge>& geometricEdgeArray,
|
||||
int i0, int i1, int f, double area);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#ifdef G3D_WINDOWS
|
||||
#pragma warning( pop )
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
84
dep/g3dlite/include/G3D/MeshBuilder.h
Normal file
84
dep/g3dlite/include/G3D/MeshBuilder.h
Normal file
@@ -0,0 +1,84 @@
|
||||
/**
|
||||
@file MeshBuilder.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-02-27
|
||||
@edited 2004-10-04
|
||||
*/
|
||||
#ifndef G3D_MESHBUILDER_H
|
||||
#define G3D_MESHBUILDER_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Triangle.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Allows creation of optimized watertight meshes from unoptimized polygon soups.
|
||||
See also G3D::MeshAlg for algorithms that operate on the output.
|
||||
*/
|
||||
class MeshBuilder {
|
||||
public:
|
||||
|
||||
/**
|
||||
Set setWeldRadius to AUTO_WELD to weld vertices closer than 1/2
|
||||
the smallest edge length in a model.
|
||||
*/
|
||||
enum {AUTO_WELD = -100};
|
||||
|
||||
private:
|
||||
/** Indices of vertices in <B>or near</B> a grid cell. */
|
||||
typedef Array<int> List;
|
||||
|
||||
std::string name;
|
||||
|
||||
bool scaleAndCenter;
|
||||
|
||||
/**
|
||||
All of the triangles, as a long triangle list.
|
||||
*/
|
||||
Array<Vector3> triList;
|
||||
|
||||
void centerTriList();
|
||||
void computeBounds(Vector3& min, Vector3& max);
|
||||
|
||||
bool _twoSided;
|
||||
|
||||
/** Collapse radius */
|
||||
double close;
|
||||
|
||||
public:
|
||||
|
||||
inline MeshBuilder(bool twoSided = false, bool scaleAndCenter = true) : scaleAndCenter(scaleAndCenter), _twoSided(twoSided), close(AUTO_WELD) {}
|
||||
|
||||
/** Writes the model to the arrays, which can then be used with
|
||||
G3D::IFSModel::save and G3D::MeshAlg */
|
||||
void commit(std::string& name, Array<int>& indexArray, Array<Vector3>& vertexArray);
|
||||
|
||||
/**
|
||||
Adds a new triangle to the model. (Counter clockwise)
|
||||
*/
|
||||
void addTriangle(const Vector3& a, const Vector3& b, const Vector3& c);
|
||||
|
||||
/**
|
||||
Adds two new triangles to the model. (Counter clockwise)
|
||||
*/
|
||||
void addQuad(const Vector3& a, const Vector3& b, const Vector3& c, const Vector3& d);
|
||||
|
||||
void addTriangle(const Triangle& t);
|
||||
|
||||
void setName(const std::string& n);
|
||||
|
||||
/** Vertices within this distance are considered identical.
|
||||
Use AUTO_WELD (the default) to have the distance be a function of the model size.*/
|
||||
void setWeldRadius(double r) {
|
||||
close = r;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
134
dep/g3dlite/include/G3D/NetAddress.h
Normal file
134
dep/g3dlite/include/G3D/NetAddress.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
\file G3D/NetAddress.h
|
||||
|
||||
\created 2010-01-03
|
||||
\edited 2013-03-17
|
||||
*/
|
||||
#ifndef G3D_NetAddress_h
|
||||
#define G3D_NetAddress_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/netheaders.h"
|
||||
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class NetAddress {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
friend class LightweightConduit;
|
||||
friend class ReliableConduit;
|
||||
|
||||
/** Host byte order */
|
||||
void init(uint32 host, uint16 port);
|
||||
void init(const std::string& hostname, uint16 port);
|
||||
NetAddress(const SOCKADDR_IN& a);
|
||||
NetAddress(const struct in_addr& addr, uint16 port = 0);
|
||||
|
||||
SOCKADDR_IN addr;
|
||||
|
||||
public:
|
||||
|
||||
enum {
|
||||
/**
|
||||
Use the host portion of the IP address of the default adapter on this machine.
|
||||
*/
|
||||
// Must match ENET_HOST_ANY
|
||||
DEFAULT_ADAPTER_HOST = 0
|
||||
};
|
||||
|
||||
/**
|
||||
In host byte order.
|
||||
|
||||
\sa DEFAULT_ADAPTER_HOST
|
||||
*/
|
||||
explicit NetAddress(uint32 host, uint16 port = 0);
|
||||
|
||||
/**
|
||||
@param port Specified in host byte order (i.e., don't worry about endian issues)
|
||||
*/
|
||||
NetAddress(const std::string& hostname, uint16 port);
|
||||
|
||||
/**
|
||||
@param hostnameAndPort in the form "hostname:port" or "ip:port"
|
||||
*/
|
||||
explicit NetAddress(const std::string& hostnameAndPort);
|
||||
|
||||
/**
|
||||
@deprecated Use G3D::NetworkDevice::broadcastAddressArray()
|
||||
|
||||
@brief Creates a UDP broadcast address for use with a
|
||||
G3D::LightweightConduit.
|
||||
|
||||
UDP broadcast allows one machine to send a packet to all machines
|
||||
on the same local network. The IP portion of the address is
|
||||
0xFFFFFFFF, which indicates "broadcast" to the underlying socket
|
||||
API. This feature is not available with the connection-based TCP
|
||||
protocol abstracted by G3D::ReliableConduit; use multisend
|
||||
instead.
|
||||
*/
|
||||
static NetAddress broadcastAddress(uint16 port);
|
||||
|
||||
NetAddress();
|
||||
|
||||
static void localHostAddresses(Array<NetAddress>& array);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** @brief Returns true if this is not an illegal address. */
|
||||
bool ok() const;
|
||||
|
||||
/** @brief Returns a value in host format (i.e., don't worry about
|
||||
endian issues) */
|
||||
inline uint32 ip() const {
|
||||
return ntohl(addr.sin_addr.s_addr);
|
||||
//return ntohl(addr.sin_addr.S_un.S_addr);
|
||||
}
|
||||
|
||||
inline uint16 port() const {
|
||||
return ntohs(addr.sin_port);
|
||||
}
|
||||
|
||||
std::string ipString() const;
|
||||
std::string toString() const;
|
||||
|
||||
/** Name of this address, without the domain. Performs reverse DNS lookup on this address. This may make a network
|
||||
connection to a DNS server and block until that communication completes
|
||||
if the address is one that has not been recently checked.*/
|
||||
std::string hostname() const;
|
||||
|
||||
/** Name of the local machine machine, without the domain. The value is cached after the first call.*/
|
||||
static std::string localHostname();
|
||||
};
|
||||
|
||||
std::ostream& operator<<(std::ostream& os, const NetAddress&);
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
template <> struct HashTrait<G3D::NetAddress> {
|
||||
static size_t hashCode(const G3D::NetAddress& key) {
|
||||
return static_cast<size_t>(key.ip() + (static_cast<G3D::uint32>(key.port()) << 16));
|
||||
}
|
||||
};
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Two addresses may point to the same computer but be != because
|
||||
they have different IP's.
|
||||
*/
|
||||
inline bool operator==(const NetAddress& a, const NetAddress& b) {
|
||||
return (a.ip() == b.ip()) && (a.port() == b.port());
|
||||
}
|
||||
|
||||
|
||||
inline bool operator!=(const NetAddress& a, const NetAddress& b) {
|
||||
return !(a == b);
|
||||
}
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
743
dep/g3dlite/include/G3D/NetworkDevice.h
Normal file
743
dep/g3dlite/include/G3D/NetworkDevice.h
Normal file
@@ -0,0 +1,743 @@
|
||||
/**
|
||||
@file NetworkDevice.h
|
||||
These classes abstract networking from the socket level to a
|
||||
serialized messaging style that is more appropriate for games. The
|
||||
performance has been tuned for sending many small messages. The
|
||||
message protocol contains a header that prevents them from being used
|
||||
with raw UDP/TCP (e.g. connecting to an HTTP server).
|
||||
|
||||
LightweightConduit and ReliableConduits have different interfaces
|
||||
because they have different semantics. You would never want to
|
||||
interchange them without rewriting the surrounding code.
|
||||
|
||||
NetworkDevice creates conduits because they need access to a global
|
||||
log pointer and because I don't want non-reference counted conduits
|
||||
being created.
|
||||
|
||||
Be careful with threads and reference counting. The reference
|
||||
counters are not threadsafe, and are also not updated correctly if a
|
||||
thread is explicitly killed. Since the conduits will be passed by
|
||||
const XConduitRef& most of the time this doesn't appear as a major
|
||||
problem. With non-blocking conduits, you should need few threads
|
||||
anyway.
|
||||
|
||||
LightweightConduits preceed each message with a 4-byte host order
|
||||
unsigned integer that is the message type. This does not appear in
|
||||
the message serialization/deserialization.
|
||||
|
||||
ReliableConduits preceed each message with two 4-byte host order
|
||||
unsigned integers. The first is the message type and the second
|
||||
indicates the length of the rest of the data. The size does not
|
||||
include the size of the header itself. The minimum message is 9
|
||||
bytes:a 4-byte type, a 4-byte header equal to "1", and one byte of data.
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
@created 2002-11-22
|
||||
@edited 2006-11-25
|
||||
*/
|
||||
|
||||
#ifndef G3D_NETWORKDEVICE_H
|
||||
#define G3D_NETWORKDEVICE_H
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/NetAddress.h"
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/BinaryOutput.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class TextOutput;
|
||||
/** \deprecated */
|
||||
class Conduit : public ReferenceCountedObject {
|
||||
protected:
|
||||
friend class NetworkDevice;
|
||||
friend class NetListener;
|
||||
|
||||
uint64 mSent;
|
||||
uint64 mReceived;
|
||||
uint64 bSent;
|
||||
uint64 bReceived;
|
||||
|
||||
SOCKET sock;
|
||||
|
||||
/**
|
||||
Used for serialization. One per socket
|
||||
to make this threadsafe.
|
||||
*/
|
||||
BinaryOutput binaryOutput;
|
||||
|
||||
Conduit();
|
||||
|
||||
public:
|
||||
|
||||
virtual ~Conduit();
|
||||
uint64 bytesSent() const;
|
||||
uint64 messagesSent() const;
|
||||
uint64 bytesReceived() const;
|
||||
uint64 messagesReceived() const;
|
||||
|
||||
/**
|
||||
If true, receive will return true.
|
||||
*/
|
||||
virtual bool messageWaiting();
|
||||
|
||||
/**
|
||||
Returns the type of the waiting message (i.e. the type supplied
|
||||
with send). The return value is zero when there is no message
|
||||
waiting.
|
||||
|
||||
One way to use this is to have a Table mapping message types to
|
||||
pre-allocated subclasses so receiving looks like:
|
||||
|
||||
<PRE>
|
||||
// My base class for messages.
|
||||
class Message {
|
||||
virtual void serialize(BinaryOutput&) const;
|
||||
virtual void deserialize(BinaryInput&);
|
||||
virtual void process() = 0;
|
||||
};
|
||||
|
||||
Message* m = table[conduit->waitingMessageType()];
|
||||
conduit->receive(m);
|
||||
m->process();
|
||||
</PRE>
|
||||
|
||||
Another is to simply switch on the message type:
|
||||
|
||||
<pre>
|
||||
switch (conduit->waitingMessageType()) {
|
||||
case 0:
|
||||
// No message
|
||||
break;
|
||||
|
||||
case ENTITY_SPAWN_MSG:
|
||||
{
|
||||
EntitySpawnMsg m;
|
||||
condiut->receive(m);
|
||||
spawnEntity(m.id, m.position, m.modelID);
|
||||
}
|
||||
break;
|
||||
...
|
||||
}
|
||||
</pre>
|
||||
*/
|
||||
virtual uint32 waitingMessageType() = 0;
|
||||
|
||||
/** Returns true if the connection is ok. */
|
||||
bool ok() const;
|
||||
};
|
||||
|
||||
typedef shared_ptr<class ReliableConduit> ReliableConduitRef;
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Workaround for a known bug in gcc 4.x where htonl produces
|
||||
// a spurrious warning.
|
||||
// http://gcc.gnu.org/ml/gcc-bugs/2005-10/msg03270.html
|
||||
uint32 gcchtonl(uint32);
|
||||
#endif
|
||||
|
||||
// Messaging and stream APIs must be supported on a single class because
|
||||
// sometimes an application will switch modes on a single socket. For
|
||||
// example, when transferring 3D level geometry during handshaking with
|
||||
// a game server.
|
||||
/**
|
||||
A conduit that guarantees messages will arrive, intact and in order.
|
||||
Create on the client using NetworkDevice::createReliableConduit and
|
||||
on the server using NetListener::waitForConnection. Set the reference
|
||||
counted pointer to NULL to disconnect.
|
||||
|
||||
To construct a ReliableConduit:
|
||||
<OL>
|
||||
<LI> Create a G3D::NetworkDevice (if you are using G3D::GApp, it creates
|
||||
one for you) on the client and on the server.
|
||||
<LI> On the server, create a G3D::NetListener using
|
||||
G3D::NetworkDevice::createListener
|
||||
<LI> On the server, invoke G3D::NetListener::waitForConnection.
|
||||
<LI> On the client, call G3D::NetworkDevice::createReliableConduit.
|
||||
You will need the server's G3D::NetAddress. Consider using
|
||||
G3D::Discovery::Client to find it via broadcasting.
|
||||
</OL>
|
||||
\deprecated
|
||||
*/
|
||||
class ReliableConduit : public Conduit {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
friend class NetListener;
|
||||
|
||||
enum State {RECEIVING, HOLDING, NO_MESSAGE} state;
|
||||
|
||||
NetAddress addr;
|
||||
|
||||
/**
|
||||
Type of the incoming message.
|
||||
*/
|
||||
uint32 messageType;
|
||||
|
||||
/**
|
||||
Total size of the incoming message (read from the header).
|
||||
*/
|
||||
uint32 messageSize;
|
||||
|
||||
/** Shared buffer for receiving messages. */
|
||||
void* receiveBuffer;
|
||||
|
||||
/** Total size of the receiveBuffer. */
|
||||
size_t receiveBufferTotalSize;
|
||||
|
||||
/** Size occupied by the current message... so far. This will be
|
||||
equal to messageSize when the whole message has arrived.
|
||||
*/
|
||||
size_t receiveBufferUsedSize;
|
||||
|
||||
ReliableConduit(const NetAddress& addr);
|
||||
|
||||
ReliableConduit(const SOCKET& sock,
|
||||
const NetAddress& addr);
|
||||
|
||||
template<typename T> static void serializeMessage
|
||||
(uint32 t, const T& m, BinaryOutput& b) {
|
||||
|
||||
b.writeUInt32(t);
|
||||
|
||||
// Reserve space for the 4 byte size header
|
||||
b.writeUInt32(0);
|
||||
|
||||
size_t L = (size_t)b.length();
|
||||
m.serialize(b);
|
||||
if ((size_t)b.length() == L) {
|
||||
// No data was created by serialization.
|
||||
// We need to send at least one byte because receive assumes that
|
||||
// a zero length message is an error.
|
||||
b.writeUInt8(0xFF);
|
||||
}
|
||||
|
||||
uint32 len = (uint32)b.size() - 8;
|
||||
|
||||
// We send the length first to tell recv how much data to read.
|
||||
// Here we abuse BinaryOutput a bit and write directly into
|
||||
// its buffer, violating the abstraction.
|
||||
// Note that we write to the second set of 4 bytes, which is
|
||||
// the size field.
|
||||
uint32* lenPtr = ((uint32*)b.getCArray()) + 1;
|
||||
#if defined(__GNUC__)
|
||||
*lenPtr = gcchtonl(len);
|
||||
#else
|
||||
*lenPtr = htonl(len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void sendBuffer(const BinaryOutput& b);
|
||||
|
||||
/** Accumulates whatever part of the message (not the header) is
|
||||
still waiting on the socket into the receiveBuffer during
|
||||
state = RECEIVING mode. Closes the socket if anything goes
|
||||
wrong. When receiveBufferUsedSize == messageSize, the entire
|
||||
message has arrived. */
|
||||
void receiveIntoBuffer();
|
||||
|
||||
/** Receives the messageType and messageSize from the socket. */
|
||||
void receiveHeader();
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Client invokes this to connect to a server. The call blocks until the
|
||||
conduit is opened. The conduit will not be ok() if it fails.
|
||||
*/
|
||||
static ReliableConduitRef create(const NetAddress& address);
|
||||
|
||||
/** Closes the socket. */
|
||||
~ReliableConduit();
|
||||
|
||||
|
||||
/** The message is actually copied from the socket to an internal buffer during
|
||||
this call. Receive only deserializes.*/
|
||||
virtual bool messageWaiting();
|
||||
|
||||
/**
|
||||
Serializes the message and schedules it to be sent as soon as possible,
|
||||
and then returns immediately. The message can be any <B>class</B> with
|
||||
a serialize and deserialize method. On the receiving side,
|
||||
use G3D::ReliableConduit::waitingMessageType() to detect the incoming
|
||||
message and then invoke G3D::ReliableConduit::receive(msg) where msg
|
||||
is of the same class as the message that was sent.
|
||||
|
||||
The actual data sent across the network is preceeded by the
|
||||
message type and the size of the serialized message as a 32-bit
|
||||
integer. The size is sent because TCP is a stream protocol and
|
||||
doesn't have a concept of discrete messages.
|
||||
*/
|
||||
template<typename T> inline void send(uint32 type, const T& message) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, message, binaryOutput);
|
||||
sendBuffer(binaryOutput);
|
||||
}
|
||||
|
||||
/** Sends an empty message with the given type. Useful for sending
|
||||
commands that have no parameters. */
|
||||
void send(uint32 type);
|
||||
|
||||
/** Send the same message to a number of conduits. Useful for sending
|
||||
data from a server to many clients (only serializes once). */
|
||||
template<typename T>
|
||||
inline static void multisend(
|
||||
const Array<ReliableConduitRef>& array,
|
||||
uint32 type,
|
||||
const T& m) {
|
||||
|
||||
if (array.size() > 0) {
|
||||
array[0]->binaryOutput.reset();
|
||||
serializeMessage(type, m, array[0]->binaryOutput);
|
||||
|
||||
for (int i = 0; i < array.size(); ++i) {
|
||||
array[i]->sendBuffer(array[0]->binaryOutput);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
virtual uint32 waitingMessageType();
|
||||
|
||||
/**
|
||||
If a message is waiting, deserializes the waiting message into
|
||||
message and returns true, otherwise returns false. You can
|
||||
determine the type of the message (and therefore, the class
|
||||
of message) using G3D::ReliableConduit::waitingMessageType().
|
||||
*/
|
||||
template<typename T> inline bool receive(T& message) {
|
||||
if (! messageWaiting()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
debugAssert(state == HOLDING);
|
||||
// Deserialize
|
||||
BinaryInput b((uint8*)receiveBuffer, receiveBufferUsedSize, G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
|
||||
message.deserialize(b);
|
||||
|
||||
// Don't let anyone read this message again. We leave the buffer
|
||||
// allocated for the next caller, however.
|
||||
receiveBufferUsedSize = 0;
|
||||
state = NO_MESSAGE;
|
||||
messageType = 0;
|
||||
messageSize = 0;
|
||||
|
||||
// Potentially read the next message.
|
||||
messageWaiting();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Removes the current message from the queue. */
|
||||
inline void receive() {
|
||||
if (! messageWaiting()) {
|
||||
return;
|
||||
}
|
||||
receiveBufferUsedSize = 0;
|
||||
state = NO_MESSAGE;
|
||||
messageType = 0;
|
||||
messageSize = 0;
|
||||
|
||||
// Potentially read the next message.
|
||||
messageWaiting();
|
||||
}
|
||||
|
||||
/** The address of the other end of the conduit */
|
||||
NetAddress address() const;
|
||||
};
|
||||
|
||||
|
||||
typedef shared_ptr<class LightweightConduit> LightweightConduitRef;
|
||||
|
||||
/**
|
||||
Provides fast but unreliable transfer of messages. On a LAN,
|
||||
LightweightConduit will probably never drop messages but you
|
||||
<I>might</I> get your messages out of order. On an internet
|
||||
connection it might drop messages altogether. Messages are never
|
||||
corrupted, however. LightweightConduit requires a little less setup
|
||||
and overhead than ReliableConduit. ReliableConduit guarantees
|
||||
message delivery and order but requires a persistent connection.
|
||||
|
||||
To set up a LightweightConduit (assuming you have already made
|
||||
subclasses of G3D::NetMessage based on your application's
|
||||
pcommunication protocol):
|
||||
|
||||
[Server Side]
|
||||
<OL>
|
||||
<LI> Call LightweightConduit::create(port, true, false),
|
||||
where port is the port on which you will receive messages.
|
||||
|
||||
<LI> Poll LightweightConduit::messageWaiting from your main loop. When
|
||||
it is true (or, equivalently, when LightweightConduit::waitingMessageType
|
||||
is non-zero) there is an incoming message.
|
||||
|
||||
<LI> To read the incoming message, call LightweightConduit::receive with
|
||||
the appropriate class type, which mist have a deserialize method.
|
||||
LightweightConduit::waitingMessageType tells you what class is
|
||||
needed (you make up your own message constants for your program; numbers
|
||||
under 1000 are reserved for G3D's internal use).
|
||||
|
||||
<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
|
||||
it go out of scope and the conduit cleans itself up automatically.
|
||||
</OL>
|
||||
|
||||
[Client Side]
|
||||
<OL>
|
||||
<LI> Call G3D::LightweightConduit::create(). If you will
|
||||
broadcast to all servers on a LAN, set the third optional argument to
|
||||
true (the default is false for no broadcast). You can also set up the
|
||||
receive port as if it was a server to send and receive from a single
|
||||
LightweightConduit.
|
||||
|
||||
<LI> To send, call G3D::LightweightConduit::send with the target address
|
||||
and a pointer to an instance of the message you want to send.
|
||||
|
||||
<LI> When done, simply set the G3D::LightweightConduitRef to NULL or let
|
||||
it go out of scope and the conduit cleans itself up automatically.
|
||||
|
||||
</OL>
|
||||
|
||||
\deprecated
|
||||
*/
|
||||
class LightweightConduit : public Conduit {
|
||||
private:
|
||||
friend class NetworkDevice;
|
||||
|
||||
/**
|
||||
True when waitingForMessageType has read the message
|
||||
from the network into messageType/messageStream.
|
||||
*/
|
||||
bool alreadyReadMessage;
|
||||
|
||||
/**
|
||||
Origin of the received message.
|
||||
*/
|
||||
NetAddress messageSender;
|
||||
|
||||
/**
|
||||
The type of the last message received.
|
||||
*/
|
||||
uint32 messageType;
|
||||
|
||||
/**
|
||||
The message received (the type has already been read off).
|
||||
*/
|
||||
Array<uint8> messageBuffer;
|
||||
|
||||
LightweightConduit(uint16 receivePort, bool enableReceive, bool enableBroadcast);
|
||||
|
||||
void sendBuffer(const NetAddress& a, BinaryOutput& b);
|
||||
|
||||
/** Maximum transmission unit (packet size in bytes) for this socket.
|
||||
May vary between sockets. */
|
||||
int MTU;
|
||||
|
||||
|
||||
template<typename T>
|
||||
void serializeMessage(
|
||||
uint32 type,
|
||||
const T& m,
|
||||
BinaryOutput& b) const {
|
||||
|
||||
debugAssert(type != 0);
|
||||
b.writeUInt32(type);
|
||||
m.serialize(b);
|
||||
b.writeUInt32(1);
|
||||
|
||||
debugAssertM(b.size() < MTU,
|
||||
format("This LightweightConduit is limited to messages of "
|
||||
"%d bytes (Ethernet hardware limit; this is the "
|
||||
"'UDP MTU')", maxMessageSize()));
|
||||
|
||||
if (b.size() >= MTU) {
|
||||
throw LightweightConduit::PacketSizeException(
|
||||
format("This LightweightConduit is limited to messages of "
|
||||
"%d bytes (Ethernet hardware limit; this is the "
|
||||
"'UDP MTU')", maxMessageSize()),
|
||||
(int)b.size() - 4, // Don't count the type header
|
||||
maxMessageSize());
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
static LightweightConduitRef create(uint16 receivePort, bool enableReceive, bool enableBroadcast);
|
||||
|
||||
class PacketSizeException {
|
||||
public:
|
||||
std::string message;
|
||||
int serializedPacketSize;
|
||||
int maxMessageSize;
|
||||
|
||||
inline PacketSizeException(const std::string& m, int s, int b) :
|
||||
message(m),
|
||||
serializedPacketSize(s),
|
||||
maxMessageSize(b) {}
|
||||
};
|
||||
|
||||
/** Closes the socket. */
|
||||
~LightweightConduit();
|
||||
|
||||
/** The maximum length of a message that can be sent
|
||||
(G3D places a small header at the front of each UDP packet;
|
||||
this is already taken into account by the value returned).
|
||||
*/
|
||||
inline int maxMessageSize() const {
|
||||
return MTU - 4;
|
||||
}
|
||||
|
||||
|
||||
template<typename T> inline void send(const NetAddress& a, uint32 type, const T& msg) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, msg, binaryOutput);
|
||||
sendBuffer(a, binaryOutput);
|
||||
}
|
||||
|
||||
/** Send the same message to multiple addresses (only serializes once).
|
||||
Useful when server needs to send to a known list of addresses
|
||||
(unlike direct UDP broadcast to all addresses on the subnet) */
|
||||
template<typename T> inline void send(const Array<NetAddress>& a, uint32 type, const T& m) {
|
||||
binaryOutput.reset();
|
||||
serializeMessage(type, m, binaryOutput);
|
||||
|
||||
for (int i = 0; i < a.size(); ++i) {
|
||||
sendBuffer(a[i], binaryOutput);
|
||||
}
|
||||
}
|
||||
|
||||
bool receive(NetAddress& sender);
|
||||
|
||||
template<typename T> inline bool receive(NetAddress& sender, T& message) {
|
||||
bool r = receive(sender);
|
||||
if (r) {
|
||||
BinaryInput b((messageBuffer.getCArray() + 4),
|
||||
messageBuffer.size() - 4,
|
||||
G3D_LITTLE_ENDIAN, BinaryInput::NO_COPY);
|
||||
message.deserialize(b);
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
inline bool receive() {
|
||||
static NetAddress ignore;
|
||||
return receive(ignore);
|
||||
}
|
||||
|
||||
virtual uint32 waitingMessageType();
|
||||
|
||||
|
||||
virtual bool messageWaiting();
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
typedef shared_ptr<class NetListener> NetListenerRef;
|
||||
|
||||
/**
|
||||
Runs on the server listening for clients trying to make reliable connections.
|
||||
|
||||
\deprecated
|
||||
*/
|
||||
class NetListener : public ReferenceCountedObject {
|
||||
private:
|
||||
|
||||
friend class NetworkDevice;
|
||||
|
||||
SOCKET sock;
|
||||
|
||||
/** Port is in host byte order. */
|
||||
NetListener(uint16 port);
|
||||
|
||||
public:
|
||||
|
||||
static NetListenerRef create(const uint16 port);
|
||||
|
||||
~NetListener();
|
||||
|
||||
/** Block until a connection is received. Returns NULL if
|
||||
something went wrong. */
|
||||
ReliableConduitRef waitForConnection();
|
||||
|
||||
/** True if a client is waiting (i.e. waitForConnection will
|
||||
return immediately). */
|
||||
bool clientWaiting() const;
|
||||
|
||||
bool ok() const;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
@brief Abstraction of network (socket) functionality.
|
||||
|
||||
An abstraction over sockets that provides a message-based network
|
||||
infrastructure optimized for sending many small (~500 bytes) messages.
|
||||
All functions always return immediately.
|
||||
|
||||
Create only one NetworkDevice per process (a WinSock restriction).
|
||||
|
||||
NetworkDevice is technically not thread safe. However, as long as
|
||||
you use different conduits on different threads (or lock conduits
|
||||
before sending), you will encounter no problems sharing the single
|
||||
NetworkDevice across multiple threads. That is, do not invoke the same
|
||||
Conduit's send or receive method on two threads at once.
|
||||
|
||||
This assumes that the underlying WinSock/BSD sockets implementation
|
||||
is thread safe. That is not guaranteed, but in practice seems
|
||||
to always be true (see
|
||||
http://tangentsoft.net/wskfaq/intermediate.html#threadsafety)
|
||||
|
||||
<hr>
|
||||
|
||||
IP networks use "network byte order" (big-endian) for
|
||||
communicating integers. "Host byte order" is the endian-ness of
|
||||
the local machine (typically little-endian; see
|
||||
System::endian). The C functions htonl() and ntohl() convert 32-bit
|
||||
values between these formats. G3D only ever exposes host byte order,
|
||||
so programmers rarely need to be aware of the distinction.
|
||||
|
||||
\deprecated
|
||||
*/
|
||||
class NetworkDevice {
|
||||
public:
|
||||
|
||||
/** @brief Description of an ethernet or wireless ethernet adapter.*/
|
||||
class EthernetAdapter {
|
||||
public:
|
||||
/** Reverse-DNS of the ip address.*/
|
||||
std::string hostname;
|
||||
|
||||
/** Name of the adapter */
|
||||
std::string name;
|
||||
|
||||
/** IP address in host byte order.*/
|
||||
uint32 ip;
|
||||
|
||||
/** Subnet mask in host byte order.*/
|
||||
uint32 subnet;
|
||||
|
||||
/** UDP broadcast address in host byte order.*/
|
||||
uint32 broadcast;
|
||||
|
||||
/** MAC (hardware) address, if known */
|
||||
uint8 mac[6];
|
||||
|
||||
EthernetAdapter();
|
||||
|
||||
/** Produces a text description of this adapter */
|
||||
void describe(TextOutput& t) const;
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
friend class Conduit;
|
||||
friend class LightweightConduit;
|
||||
friend class ReliableConduit;
|
||||
friend class NetListener;
|
||||
|
||||
bool initialized;
|
||||
|
||||
Array<EthernetAdapter> m_adapterArray;
|
||||
|
||||
/** Broadcast addresses available on this machine,
|
||||
extracted from m_adapterArray.*/
|
||||
Array<uint32> m_broadcastAddresses;
|
||||
|
||||
/** Utility method. */
|
||||
void closesocket(SOCKET& sock) const;
|
||||
|
||||
/** Utility method. Returns true on success.*/
|
||||
bool bind(SOCKET sock, const NetAddress& addr) const;
|
||||
|
||||
/** The global instance */
|
||||
static NetworkDevice* s_instance;
|
||||
|
||||
NetworkDevice();
|
||||
|
||||
bool init();
|
||||
|
||||
void _cleanup();
|
||||
|
||||
/** Called from init to update m_adapterArray and
|
||||
m_broadcastAddresses. */
|
||||
void addAdapter(const EthernetAdapter& a);
|
||||
|
||||
public:
|
||||
|
||||
/** Prints an IP address to a string.
|
||||
@param ip In host byte order.*/
|
||||
static std::string formatIP(uint32 ip);
|
||||
|
||||
/** Prints a MAC address to a string. */
|
||||
static std::string formatMAC(const uint8 mac[6]);
|
||||
|
||||
~NetworkDevice();
|
||||
|
||||
/** Returns the available ethernet adapters for the current
|
||||
machine that are online. Does not include the loopback adapter
|
||||
for localhost.*/
|
||||
inline const Array<EthernetAdapter>& adapterArray() const {
|
||||
return m_adapterArray;
|
||||
}
|
||||
|
||||
/** Returns the (unique) IP addresses for UDP broadcasting
|
||||
extracted from adapterArray(). All are in host byte order. */
|
||||
inline const Array<uint32>& broadcastAddressArray() const {
|
||||
return m_broadcastAddresses;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns NULL if there was a problem initializing the network.
|
||||
*/
|
||||
static NetworkDevice* instance();
|
||||
|
||||
/**
|
||||
Shuts down the network device (destroying the global instance).
|
||||
*/
|
||||
static void cleanup();
|
||||
|
||||
/**
|
||||
Prints a human-readable description of this machine
|
||||
to the text output stream.
|
||||
*/
|
||||
void describeSystem(
|
||||
TextOutput& t);
|
||||
|
||||
void describeSystem(
|
||||
std::string& s);
|
||||
|
||||
/** Returns the name (or one of the names) of this computer */
|
||||
std::string localHostName() const;
|
||||
|
||||
/** There is often more than one address for the local host. This
|
||||
returns all of them.
|
||||
@deprecated Use adapterArray()
|
||||
*/
|
||||
void localHostAddresses(Array<NetAddress>& array) const;
|
||||
};
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
inline uint32 gcchtonl(uint32 x) {
|
||||
// This pragma fools gcc into surpressing all error messages,
|
||||
// including the bogus one that it creates for htonl
|
||||
# pragma GCC system_header
|
||||
return htonl(x);
|
||||
}
|
||||
#endif
|
||||
|
||||
} // G3D namespace
|
||||
|
||||
#ifndef _WIN32
|
||||
#undef SOCKADDR_IN
|
||||
#undef SOCKET
|
||||
#endif
|
||||
|
||||
#endif
|
||||
62
dep/g3dlite/include/G3D/ParseError.h
Normal file
62
dep/g3dlite/include/G3D/ParseError.h
Normal file
@@ -0,0 +1,62 @@
|
||||
/**
|
||||
@file ParseError.h
|
||||
|
||||
@maintainer Morgan McGuire
|
||||
|
||||
@created 2009-11-15
|
||||
@edited 2009-11-15
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_ParseError_h
|
||||
#define G3D_ParseError_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Thrown by TextInput, Any, and other parsers on unexpected input. */
|
||||
class ParseError {
|
||||
public:
|
||||
enum {UNKNOWN = -1};
|
||||
|
||||
/** Empty means unknown */
|
||||
std::string filename;
|
||||
|
||||
/** For a binary file, the location of the parse error. -1 if unknown.*/
|
||||
int64 byte;
|
||||
|
||||
/** For a text file, the line number is the line number of start of token which caused the exception. 1 is
|
||||
the first line of the file. -1 means unknown. Note that you can use
|
||||
TextInput::Settings::startingLineNumberOffset to shift the effective line
|
||||
number that is reported by that class.
|
||||
*/
|
||||
int line;
|
||||
|
||||
/** Character number (in the line) of the start of the token which caused the
|
||||
exception. 1 is the character in the line. May be -1 if unknown.
|
||||
*/
|
||||
int character;
|
||||
|
||||
std::string message;
|
||||
|
||||
ParseError() : byte(UNKNOWN), line(UNKNOWN), character(UNKNOWN) {}
|
||||
|
||||
virtual ~ParseError() {}
|
||||
|
||||
ParseError(const std::string& f, int l, int c, const std::string& m) :
|
||||
filename (f), byte(UNKNOWN), line(l), character(c), message(m) {}
|
||||
|
||||
ParseError(const std::string& f, int64 b, const std::string& m) :
|
||||
filename (f), byte(b), line(UNKNOWN), character(UNKNOWN), message(m) {}
|
||||
|
||||
/** If information is known, ends in ": ", otherwise empty */
|
||||
std::string formatFileInfo() const;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
128
dep/g3dlite/include/G3D/PhysicsFrame.h
Normal file
128
dep/g3dlite/include/G3D/PhysicsFrame.h
Normal file
@@ -0,0 +1,128 @@
|
||||
/**
|
||||
\file PhysicsFrame.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2002-07-08
|
||||
\edited 2011-05-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_PhysicsFrame_h
|
||||
#define G3D_PhysicsFrame_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Matrix3.h"
|
||||
#include "G3D/Quat.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
#include <math.h>
|
||||
#include <string>
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An RT transformation using a quaternion; suitable for
|
||||
physics integration.
|
||||
|
||||
This interface is in "Beta" and will change in the next release.
|
||||
*/
|
||||
class PhysicsFrame {
|
||||
public:
|
||||
|
||||
Quat rotation;
|
||||
|
||||
/**
|
||||
Origin of this reference frame in its parent's frame.
|
||||
*/
|
||||
Point3 translation;
|
||||
|
||||
/**
|
||||
Initializes to the identity frame.
|
||||
*/
|
||||
PhysicsFrame();
|
||||
|
||||
/**
|
||||
Purely translational.
|
||||
*/
|
||||
PhysicsFrame(const Vector3& translation) : translation(translation) {}
|
||||
PhysicsFrame(const Quat& rot, const Vector3& translation) : rotation(rot), translation(translation) {}
|
||||
PhysicsFrame(const Matrix3& rot, const Vector3& translation) : rotation(rot), translation(translation) {}
|
||||
PhysicsFrame(const Matrix3& rot) : rotation(rot), translation(Vector3::zero()) {}
|
||||
PhysicsFrame(const CoordinateFrame& coordinateFrame);
|
||||
|
||||
PhysicsFrame& operator=(const PhysicsFrame& p) {
|
||||
rotation = p.rotation;
|
||||
translation = p.translation;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
- PhysicsFrame( [quat], [vec3] )
|
||||
- Vector3( ... )
|
||||
- CFrame( ... )
|
||||
- CFrame::from...( ... )
|
||||
*/
|
||||
PhysicsFrame(const class Any& any);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
/** Compose: create the transformation that is <I>other</I> followed by <I>this</I>.*/
|
||||
PhysicsFrame operator*(const PhysicsFrame& other) const;
|
||||
|
||||
virtual ~PhysicsFrame() {}
|
||||
|
||||
/**
|
||||
Linear interpolation (spherical linear for the rotations).
|
||||
*/
|
||||
PhysicsFrame lerp(
|
||||
const PhysicsFrame& other,
|
||||
float alpha) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
operator CFrame() const;
|
||||
|
||||
/** Multiplies both pieces by \a f; note that this will result in a non-unit
|
||||
quaternion that needs to be normalized */
|
||||
PhysicsFrame& operator*=(float f) {
|
||||
rotation *= f;
|
||||
translation *= f;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Multiplies both pieces by \a f; note that this will result in a non-unit
|
||||
quaternion that needs to be normalized */
|
||||
PhysicsFrame operator*(float f) const {
|
||||
return PhysicsFrame(rotation * f, translation * f);
|
||||
}
|
||||
|
||||
PhysicsFrame operator+(const PhysicsFrame& f) const {
|
||||
return PhysicsFrame(rotation + f.rotation, translation + f.translation);
|
||||
}
|
||||
|
||||
PhysicsFrame& operator+=(const PhysicsFrame& f) {
|
||||
rotation += f.rotation;
|
||||
translation += f.translation;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const PhysicsFrame& other) const {
|
||||
return (translation == other.translation) &&
|
||||
((rotation == other.rotation) || (rotation == -other.rotation));
|
||||
}
|
||||
|
||||
bool operator!=(const PhysicsFrame& other) const {
|
||||
return ! ((*this) == other);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
typedef PhysicsFrame PFrame;
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
52
dep/g3dlite/include/G3D/PhysicsFrameSpline.h
Normal file
52
dep/g3dlite/include/G3D/PhysicsFrameSpline.h
Normal file
@@ -0,0 +1,52 @@
|
||||
/**
|
||||
@file PhysicsFrameSpline.h
|
||||
|
||||
@author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
#ifndef G3D_PhysicsFrameSpline_h
|
||||
#define G3D_PhysicsFrameSpline_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/PhysicsFrame.h"
|
||||
#include "G3D/Spline.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
A subclass of Spline that keeps the rotation field of a
|
||||
PhysicsFrame normalized and rotating the short direction.
|
||||
|
||||
\sa UprightFrameSpline
|
||||
*/
|
||||
class PhysicsFrameSpline : public Spline<PhysicsFrame> {
|
||||
public:
|
||||
|
||||
PhysicsFrameSpline();
|
||||
|
||||
/** Accepts a table of properties, or any valid PhysicsFrame specification for a single control*/
|
||||
PhysicsFrameSpline(const Any& any);
|
||||
|
||||
bool operator==(const PhysicsFrameSpline& a) const;
|
||||
|
||||
bool operator!=(const PhysicsFrameSpline& a) const {
|
||||
return ! ((*this) == a);
|
||||
}
|
||||
|
||||
/** Mutates all underlying PhysicsFrames by scaling their translation by \param scaleFactor */
|
||||
void scaleControlPoints(float scaleFactor);
|
||||
|
||||
virtual void correct(PhysicsFrame& frame) const;
|
||||
virtual void ensureShortestPath(PhysicsFrame* A, int N) const;
|
||||
|
||||
virtual Any toAny(const std::string& myName) const override {
|
||||
return Spline<PhysicsFrame>::toAny(myName);
|
||||
}
|
||||
|
||||
Any toAny() const {
|
||||
return toAny("PFrameSpline");
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
169
dep/g3dlite/include/G3D/Plane.h
Normal file
169
dep/g3dlite/include/G3D/Plane.h
Normal file
@@ -0,0 +1,169 @@
|
||||
/**
|
||||
\file Plane.h
|
||||
|
||||
Plane class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-06-02
|
||||
\edited 2010-12-04
|
||||
*/
|
||||
|
||||
#ifndef G3D_Plane_h
|
||||
#define G3D_Plane_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/debugAssert.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) {
|
||||
}
|
||||
|
||||
/** Format is:
|
||||
- Plane(normal, point)
|
||||
*/
|
||||
explicit Plane(const class Any& a);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
/**
|
||||
Constructs a plane from three points.
|
||||
*/
|
||||
Plane
|
||||
(const Point3& point0,
|
||||
const Point3& point1,
|
||||
const Point3& 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 Point3& point);
|
||||
|
||||
static Plane fromEquation(float a, float b, float c, float d);
|
||||
|
||||
Plane(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
virtual ~Plane() {}
|
||||
|
||||
/**
|
||||
Returns true if point is on the side the normal points to or
|
||||
is in the plane.
|
||||
*/
|
||||
inline bool halfSpaceContains(Point3 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 Point3& point) const {
|
||||
debugAssert(point.isFinite());
|
||||
return _normal.dot(point) >= _distance;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the point is nearly in the plane.
|
||||
*/
|
||||
inline bool fuzzyContains(const Point3& 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 Point3 closestPoint(const Point3& 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
|
||||
1045
dep/g3dlite/include/G3D/PointHashGrid.h
Normal file
1045
dep/g3dlite/include/G3D/PointHashGrid.h
Normal file
File diff suppressed because it is too large
Load Diff
1188
dep/g3dlite/include/G3D/PointKDTree.h
Normal file
1188
dep/g3dlite/include/G3D/PointKDTree.h
Normal file
File diff suppressed because it is too large
Load Diff
356
dep/g3dlite/include/G3D/Pointer.h
Normal file
356
dep/g3dlite/include/G3D/Pointer.h
Normal file
@@ -0,0 +1,356 @@
|
||||
/**
|
||||
\file Pointer.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2007-05-16
|
||||
\edited 2012-10-06
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_Pointer_h
|
||||
#define G3D_Pointer_h
|
||||
|
||||
#include "G3D/debugAssert.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Acts like a pointer to a value of type ValueType (i.e.,
|
||||
ValueType*), but can operate through accessor methods as well as on
|
||||
a value in memory. This is useful for implementing scripting
|
||||
languages and other applications that need to connect existing APIs
|
||||
by reference.
|
||||
|
||||
Because the accessors require values to be passed by value (instead of by reference)
|
||||
this is primarily useful for objects whose memory size is small.
|
||||
|
||||
\code
|
||||
class Foo {
|
||||
public:
|
||||
void setEnabled(bool b);
|
||||
bool getEnabled() const;
|
||||
};
|
||||
|
||||
Foo f;
|
||||
bool b;
|
||||
|
||||
Pointer<bool> p1(&b);
|
||||
Pointer<bool> p2(&f, &Foo::getEnabled, &Foo::setEnabled);
|
||||
|
||||
*p1 = true;
|
||||
*p2 = false;
|
||||
*p2 = *p1; \/\/ Value assignment
|
||||
p2 = p1; \/\/ Pointer aliasing
|
||||
|
||||
\/\/ Or, equivalently:
|
||||
p1.setValue(true);
|
||||
p2.setValue(false);
|
||||
|
||||
p2.setValue(p1.getValue());
|
||||
p2 = p1;
|
||||
\endcode
|
||||
|
||||
<i>Note:</i> Because of the way that dereference is implemented, you cannot pass <code>*p</code> through a function
|
||||
that takes varargs (...), e.g., <code>printf("%d", *p)</code> will produce a compile-time error. Instead use
|
||||
<code>printf("%d",(bool)*p)</code> or <code>printf("%d", p.getValue())</code>.
|
||||
|
||||
\cite McGuire, GUIs for Real-time Programs, using Universal Pointers, SIGGRAPH 2008 Poster.
|
||||
*/
|
||||
template<typename ValueType>
|
||||
class Pointer {
|
||||
private:
|
||||
|
||||
class Interface {
|
||||
public:
|
||||
virtual ~Interface() {};
|
||||
virtual void set(ValueType b) = 0;
|
||||
virtual ValueType get() const = 0;
|
||||
virtual Interface* clone() const = 0;
|
||||
virtual bool isNull() const = 0;
|
||||
};
|
||||
|
||||
class Memory : public Interface {
|
||||
private:
|
||||
|
||||
ValueType* value;
|
||||
|
||||
public:
|
||||
|
||||
Memory(ValueType* value) : value(value) {}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
*value = v;
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return *value;
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new Memory(value);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return value == NULL;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename GetMethod, typename SetMethod>
|
||||
class FcnAccessor : public Interface {
|
||||
private:
|
||||
|
||||
GetMethod getMethod;
|
||||
SetMethod setMethod;
|
||||
|
||||
public:
|
||||
|
||||
FcnAccessor(GetMethod getMethod, SetMethod setMethod) : getMethod(getMethod), setMethod(setMethod) {
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
if (setMethod) {
|
||||
(*setMethod)(v);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return (*getMethod)();
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new FcnAccessor(getMethod, setMethod);
|
||||
}
|
||||
|
||||
virtual bool isNull() const { return false; }
|
||||
};
|
||||
|
||||
template<class T, typename GetMethod, typename SetMethod>
|
||||
class Accessor : public Interface {
|
||||
private:
|
||||
|
||||
T* object;
|
||||
GetMethod getMethod;
|
||||
SetMethod setMethod;
|
||||
|
||||
public:
|
||||
|
||||
Accessor(T* object,
|
||||
GetMethod getMethod,
|
||||
SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
|
||||
debugAssert(object != NULL);
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
if (setMethod) {
|
||||
(object->*setMethod)(v);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return (object->*getMethod)();
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new Accessor(object, getMethod, setMethod);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return object == NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<class T, typename GetMethod, typename SetMethod>
|
||||
class SharedAccessor : public Interface {
|
||||
private:
|
||||
|
||||
shared_ptr<T> object;
|
||||
GetMethod getMethod;
|
||||
SetMethod setMethod;
|
||||
|
||||
public:
|
||||
|
||||
SharedAccessor
|
||||
(const shared_ptr<T>& object,
|
||||
GetMethod getMethod,
|
||||
SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
|
||||
|
||||
debugAssert(object != NULL);
|
||||
}
|
||||
|
||||
virtual void set(ValueType v) {
|
||||
if (setMethod) {
|
||||
(object.get()->*setMethod)(v);
|
||||
}
|
||||
}
|
||||
|
||||
virtual ValueType get() const {
|
||||
return (object.get()->*getMethod)();
|
||||
}
|
||||
|
||||
virtual Interface* clone() const {
|
||||
return new SharedAccessor(object, getMethod, setMethod);
|
||||
}
|
||||
|
||||
virtual bool isNull() const {
|
||||
return (bool)object;
|
||||
}
|
||||
};
|
||||
|
||||
Interface* m_interface;
|
||||
|
||||
public:
|
||||
|
||||
Pointer() : m_interface(NULL) {};
|
||||
|
||||
/** Allows implicit cast from real pointer */
|
||||
Pointer(ValueType* v) : m_interface(new Memory(v)) {}
|
||||
|
||||
inline bool isNull() const {
|
||||
return (m_interface == NULL) || m_interface->isNull();
|
||||
}
|
||||
|
||||
// Assignment
|
||||
inline Pointer& operator=(const Pointer& r) {
|
||||
delete m_interface;
|
||||
if (r.m_interface != NULL) {
|
||||
m_interface = r.m_interface->clone();
|
||||
} else {
|
||||
m_interface = NULL;
|
||||
}
|
||||
return this[0];
|
||||
}
|
||||
|
||||
Pointer(const Pointer& p) : m_interface(NULL) {
|
||||
this[0] = p;
|
||||
}
|
||||
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(const shared_ptr<Class>& object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new SharedAccessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(const shared_ptr<Class>& object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new SharedAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
Pointer(ValueType (*getMethod)(),
|
||||
void (*setMethod)(ValueType)) :
|
||||
m_interface(new FcnAccessor<ValueType (*)(), void (*)(ValueType)>(getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
Pointer(const ValueType& (*getMethod)(),
|
||||
void (*setMethod)(ValueType)) :
|
||||
m_interface(new FcnAccessor<const ValueType& (*)(), void (*)(ValueType)>(getMethod, setMethod)) {}
|
||||
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(const shared_ptr<Class>& object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new SharedAccessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(const shared_ptr<Class>& object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new SharedAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(const ValueType&)) :
|
||||
m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
const ValueType& (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new Accessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
/** \param setMethod May be NULL */
|
||||
template<class Class>
|
||||
Pointer(Class* object,
|
||||
ValueType (Class::*getMethod)() const,
|
||||
void (Class::*setMethod)(ValueType)) :
|
||||
m_interface(new Accessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
|
||||
|
||||
~Pointer() {
|
||||
delete m_interface;
|
||||
}
|
||||
|
||||
inline const ValueType getValue() const {
|
||||
debugAssert(m_interface != NULL);
|
||||
return m_interface->get();
|
||||
}
|
||||
|
||||
/** \brief Assign a value to the referenced element.
|
||||
If this Pointer was initialized with a NULL setMethod, the call is ignored */
|
||||
inline void setValue(const ValueType& v) {
|
||||
debugAssert(m_interface != NULL);
|
||||
m_interface->set(v);
|
||||
}
|
||||
|
||||
class IndirectValue {
|
||||
private:
|
||||
|
||||
friend class Pointer;
|
||||
Pointer* pointer;
|
||||
IndirectValue(Pointer* p) : pointer(p) {}
|
||||
|
||||
public:
|
||||
|
||||
void operator=(const ValueType& v) {
|
||||
pointer->setValue(v);
|
||||
}
|
||||
|
||||
operator ValueType() const {
|
||||
return pointer->getValue();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline IndirectValue operator*() {
|
||||
return IndirectValue(this);
|
||||
}
|
||||
|
||||
inline const ValueType operator*() const {
|
||||
return getValue();
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
bool isNull(const Pointer<T>& p) {
|
||||
return p.isNull();
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool notNull(const Pointer<T>& p) {
|
||||
return ! p.isNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
7
dep/g3dlite/include/G3D/PositionTrait.h
Normal file
7
dep/g3dlite/include/G3D/PositionTrait.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#ifndef G3D_POSITIONTRAIT_H
|
||||
#define G3D_POSITIONTRAIT_H
|
||||
|
||||
template<typename Value>
|
||||
struct PositionTrait{};
|
||||
|
||||
#endif
|
||||
110
dep/g3dlite/include/G3D/PrecomputedRandom.h
Normal file
110
dep/g3dlite/include/G3D/PrecomputedRandom.h
Normal file
@@ -0,0 +1,110 @@
|
||||
/**
|
||||
@file PrecomputedRandom.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2009-03-31
|
||||
@edited 2009-03-31
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_PrecomputedRandom_h
|
||||
#define G3D_PrecomputedRandom_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Random.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Fast random numbers using a precomputed data table.
|
||||
|
||||
e.g., generates cosHemi about 13x faster than Random.
|
||||
This is useful for quickly generating seeded random
|
||||
numbers for reproducibility. G3D::Random takes a long
|
||||
time to seed; this is instantaneous (providing the
|
||||
precomputed data is already available.)
|
||||
|
||||
Not threadsafe.*/
|
||||
class PrecomputedRandom : public Random {
|
||||
public:
|
||||
/** Put the cosHemi and the uniform together so that when
|
||||
alternating between them we stay in cache. This is also packed
|
||||
into a good size for SIMD and GPU operations.*/
|
||||
class HemiUniformData {
|
||||
public:
|
||||
float cosHemiX;
|
||||
float cosHemiY;
|
||||
float cosHemiZ;
|
||||
float uniform;
|
||||
};
|
||||
|
||||
class SphereBitsData {
|
||||
public:
|
||||
float sphereX;
|
||||
float sphereY;
|
||||
float sphereZ;
|
||||
uint32 bits;
|
||||
};
|
||||
|
||||
protected:
|
||||
|
||||
/** Array of 2^n elements. */
|
||||
const HemiUniformData* m_hemiUniform;
|
||||
const SphereBitsData* m_sphereBits;
|
||||
|
||||
/** 2^n - 1; the AND mask for computing a fast modulo */
|
||||
int m_modMask;
|
||||
|
||||
int m_index;
|
||||
|
||||
/** If true, free m_hemiUniform and m_sphereBits in destructor */
|
||||
bool m_freeData;
|
||||
|
||||
public:
|
||||
|
||||
/*
|
||||
\param dataSize Must be a power of 2
|
||||
\param data Will NOT be deleted by the destructor.
|
||||
*/
|
||||
PrecomputedRandom(const HemiUniformData* data1, const SphereBitsData* data2, int dataSize, uint32 seed = 0xF018A4D2);
|
||||
|
||||
/**
|
||||
\param dataSize Number of random numbers that can be requested before periodicity. Must be a power of 2.
|
||||
*/
|
||||
PrecomputedRandom(int dataSize, uint32 seed = 0xF018A4D2);
|
||||
|
||||
~PrecomputedRandom();
|
||||
|
||||
/** Each bit is random. Subclasses can choose to override just
|
||||
this method and the other methods will all work automatically. */
|
||||
virtual uint32 bits();
|
||||
|
||||
// integer is inherited
|
||||
|
||||
/** Uniform random float on the range [min, max] */
|
||||
virtual float uniform(float low, float high);
|
||||
|
||||
/** Uniform random float on the range [0, 1] */
|
||||
virtual float uniform();
|
||||
|
||||
// gaussian is inherited
|
||||
|
||||
/** Returns 3D unit vectors distributed according to
|
||||
a cosine distribution about the z axis. */
|
||||
virtual void cosHemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to a cosine
|
||||
power distribution (\f$ \mbox{cos}^k \theta \f$) about
|
||||
the z-axis. */
|
||||
virtual void cosPowHemi(const float k, float& x, float& y, float& z);
|
||||
|
||||
// hemi is inherited
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the sphere */
|
||||
virtual void sphere(float& x, float& y, float& z);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
766
dep/g3dlite/include/G3D/Quat.h
Normal file
766
dep/g3dlite/include/G3D/Quat.h
Normal file
@@ -0,0 +1,766 @@
|
||||
/**
|
||||
\file G3D/Quat.h
|
||||
|
||||
Quaternion
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2002-01-23
|
||||
\edited 2011-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 {
|
||||
|
||||
/**
|
||||
Arbitrary quaternion (not necessarily unit).
|
||||
|
||||
Unit quaternions (aka versors) 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, (0,0,0,1)
|
||||
*/
|
||||
Quat() : x(0), y(0), z(0), w(1) {}
|
||||
|
||||
/** Expects "Quat(x,y,z,w)" or a Matrix3 constructor. */
|
||||
Quat(const class Any& a);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
Quat(const Matrix3& rot);
|
||||
|
||||
Quat(float _x, float _y, float _z, float _w) :
|
||||
x(_x), y(_y), z(_z), w(_w) {}
|
||||
|
||||
/** Defaults to a pure vector quaternion */
|
||||
Quat(const Vector3& v, float _w = 0) : x(v.x), y(v.y), z(v.z), w(_w) {
|
||||
}
|
||||
|
||||
/** True if the components are exactly equal. Note that two quaternations may
|
||||
be unequal but map to the same rotation. */
|
||||
bool operator==(const Quat& q) const {
|
||||
return x == q.x && y == q.y && z == q.z && w == q.w;
|
||||
}
|
||||
|
||||
/**
|
||||
The real part of the quaternion.
|
||||
*/
|
||||
const float& real() const {
|
||||
return w;
|
||||
}
|
||||
|
||||
float& real() {
|
||||
return w;
|
||||
}
|
||||
|
||||
Quat operator-() const {
|
||||
return Quat(-x, -y, -z, -w);
|
||||
}
|
||||
|
||||
Quat operator-(const Quat& other) const {
|
||||
return Quat(x - other.x, y - other.y, z - other.z, w - other.w);
|
||||
}
|
||||
|
||||
Quat& operator-=(const Quat& q) {
|
||||
x -= q.x;
|
||||
y -= q.y;
|
||||
z -= q.z;
|
||||
w -= q.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Quat operator+(const Quat& q) const {
|
||||
return Quat(x + q.x, y + q.y, z + q.z, w + q.w);
|
||||
}
|
||||
|
||||
Quat& operator+=(const Quat& q) {
|
||||
x += q.x;
|
||||
y += q.y;
|
||||
z += q.z;
|
||||
w += q.w;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Negates the imaginary part.
|
||||
*/
|
||||
Quat conj() const {
|
||||
return Quat(-x, -y, -z, w);
|
||||
}
|
||||
|
||||
float sum() const {
|
||||
return x + y + z + w;
|
||||
}
|
||||
|
||||
float average() const {
|
||||
return sum() / 4.0f;
|
||||
}
|
||||
|
||||
Quat operator*(float s) const {
|
||||
return Quat(x * s, y * s, z * s, w * s);
|
||||
}
|
||||
|
||||
Quat& operator*=(float s) {
|
||||
x *= s;
|
||||
y *= s;
|
||||
z *= s;
|
||||
w *= s;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
/** @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);
|
||||
}
|
||||
|
||||
float dot(const Quat& other) const {
|
||||
return (x * other.x) + (y * other.y) + (z * other.z) + (w * other.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);
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the imaginary part (x, y, z)
|
||||
*/
|
||||
const Vector3& imag() const {
|
||||
return *(reinterpret_cast<const Vector3*>(this));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
private:
|
||||
/** \param maxAngle Maximum angle of rotation allowed. If a larger rotation is required, the angle of rotation applied is clamped to maxAngle */
|
||||
Quat slerp
|
||||
(const Quat& other,
|
||||
float alpha,
|
||||
float threshold,
|
||||
float maxAngle) const;
|
||||
public:
|
||||
|
||||
/**
|
||||
Spherical linear interpolation: linear interpolation along the
|
||||
shortest (3D) great-circle route between two quaternions.
|
||||
|
||||
Assumes that both arguments are unit 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 (in radians) 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 {
|
||||
return slerp(other, alpha, threshold, finf());
|
||||
}
|
||||
|
||||
/** Rotates towards \a other by at most \a maxAngle. */
|
||||
Quat movedTowards
|
||||
(const Quat& other,
|
||||
float maxAngle) const {
|
||||
return slerp(other, 1.0f, 0.05f, maxAngle);
|
||||
}
|
||||
|
||||
/** Rotates towards \a other by at most \a maxAngle. */
|
||||
void moveTowards
|
||||
(const Quat& other,
|
||||
float maxAngle) {
|
||||
*this = movedTowards(other, maxAngle);
|
||||
}
|
||||
|
||||
/** Returns the angle in radians between this and other, assuming both are unit quaternions.
|
||||
|
||||
\returns On the range [0, pif()]*/
|
||||
float angleBetween(const Quat& other) const;
|
||||
|
||||
/** Normalized linear interpolation of quaternion components. */
|
||||
Quat nlerp(const Quat& other, float alpha) const;
|
||||
|
||||
|
||||
/** Note that q<SUP>-1</SUP> = q.conj() for a unit quaternion.
|
||||
@cite Dam99 page 13 */
|
||||
inline Quat inverse() const {
|
||||
return conj() / dot(*this);
|
||||
}
|
||||
|
||||
/**
|
||||
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? */
|
||||
bool isUnit(float tolerance = 1e-5) const {
|
||||
return abs(dot(*this) - 1.0f) < tolerance;
|
||||
}
|
||||
|
||||
float magnitude() const {
|
||||
return sqrtf(dot(*this));
|
||||
}
|
||||
|
||||
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)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));
|
||||
}
|
||||
}
|
||||
|
||||
/** 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();
|
||||
}
|
||||
|
||||
/** Make unit length in place */
|
||||
void unitize() {
|
||||
*this *= rsq(dot(*this));
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a unit quaterion obtained by dividing through by
|
||||
the magnitude.
|
||||
*/
|
||||
Quat toUnit() const {
|
||||
Quat x = *this;
|
||||
x.unitize();
|
||||
return x;
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
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();
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b) 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 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;
|
||||
}
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
|
||||
} // 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);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
370
dep/g3dlite/include/G3D/Queue.h
Normal file
370
dep/g3dlite/include/G3D/Queue.h
Normal file
@@ -0,0 +1,370 @@
|
||||
/**
|
||||
@file Queue.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-09
|
||||
@edited 2008-12-20
|
||||
*/
|
||||
|
||||
#ifndef G3D_Queue_h
|
||||
#define G3D_Queue_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/System.h"
|
||||
#include "G3D/debug.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Locate the indices of the break between of the two
|
||||
sections of the circular queue. These are used to
|
||||
construct two for loops that iterate over the whole
|
||||
sequence without using the modulo operator.
|
||||
|
||||
[0 ... secondEnd) [head .... firstEnd)
|
||||
|
||||
\sa ThreadsafeQueue
|
||||
*/
|
||||
#define FIND_ENDS \
|
||||
int firstEnd = head + num;\
|
||||
int secondEnd = 0;\
|
||||
if (firstEnd > numAllocated) {\
|
||||
secondEnd = firstEnd - numAllocated;\
|
||||
firstEnd = numAllocated;\
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Dynamic queue that uses a circular buffer for performance.
|
||||
|
||||
Faster than std::deque for objects with constructors.
|
||||
*/
|
||||
template <class T>
|
||||
class Queue {
|
||||
private:
|
||||
//
|
||||
// |<---- num ---->|
|
||||
// [ | | | | | | | | | | | | | ]
|
||||
// ^
|
||||
// |
|
||||
// head
|
||||
//
|
||||
//
|
||||
|
||||
/**
|
||||
Only num elements are initialized.
|
||||
*/
|
||||
T* data;
|
||||
|
||||
/**
|
||||
Index of the next element to be dequeue-d in data.
|
||||
*/
|
||||
int head;
|
||||
|
||||
/**
|
||||
Number of elements (including head) that are visible and initialized.
|
||||
*/
|
||||
int num;
|
||||
|
||||
/**
|
||||
Size of data array in elements.
|
||||
*/
|
||||
int numAllocated;
|
||||
|
||||
/** If a clear was needed, assumes it already occured */
|
||||
void _copy(const Queue& other) {
|
||||
debugAssert(data == NULL);
|
||||
data = (T*)System::malloc(sizeof(T) * other.numAllocated);
|
||||
debugAssert(data);
|
||||
head = other.head;
|
||||
num = other.num;
|
||||
numAllocated = other.numAllocated;
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
for (int i = head; i < firstEnd; ++i) {
|
||||
new (data + i)T(other.data[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondEnd; ++i) {
|
||||
new (data + i)T(other.data[i]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Computes a data array index from a queue position. The queue position
|
||||
may be negative.
|
||||
*/
|
||||
inline int index(int i) const {
|
||||
return (head + i + numAllocated) % numAllocated;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocates newSize elements and repacks the array.
|
||||
*/
|
||||
void repackAndRealloc(int newSize) {
|
||||
// TODO: shrink queue
|
||||
T* old = data;
|
||||
data = (T*)System::malloc(newSize * sizeof(T));
|
||||
debugAssert(data != NULL);
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
int j = 0;
|
||||
for (int i = head; i < firstEnd; ++i, ++j) {
|
||||
new (data + j)T(old[i]);
|
||||
(old + i)->~T();
|
||||
}
|
||||
|
||||
for (int i = 0; i < secondEnd; ++i, ++j) {
|
||||
new (data + j)T(old[i]);
|
||||
(old + i)->~T();
|
||||
}
|
||||
|
||||
head = 0;
|
||||
System::free(old);
|
||||
numAllocated = newSize;
|
||||
}
|
||||
|
||||
/**
|
||||
Ensure that there is at least one element between
|
||||
the tail and head, wrapping around in the circular
|
||||
buffer.
|
||||
*/
|
||||
inline void reserveSpace() {
|
||||
if (num == numAllocated) {
|
||||
repackAndRealloc(numAllocated * 3 + 20);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
Queue() :
|
||||
data(NULL),
|
||||
head(0),
|
||||
num(0),
|
||||
numAllocated(0) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Copy constructor
|
||||
*/
|
||||
Queue(const Queue& other) : data(NULL) {
|
||||
_copy(other);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Destructor does not delete() the objects if T is a pointer type
|
||||
(e.g. T = int*) instead, it deletes the pointers themselves and
|
||||
leaves the objects. Call deleteAll if you want to dealocate
|
||||
the objects referenced.
|
||||
*/
|
||||
virtual ~Queue() {
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a new element into the front of the queue
|
||||
(a traditional queue only uses pushBack).
|
||||
*/
|
||||
inline void pushFront(const T& e) {
|
||||
reserveSpace();
|
||||
|
||||
// Get the index of head-1
|
||||
int i = index(-1);
|
||||
|
||||
// Call the constructor on the newly exposed element.
|
||||
new (data + i)T(e);
|
||||
|
||||
// Reassign the head to point to this index
|
||||
head = i;
|
||||
++num;
|
||||
}
|
||||
|
||||
/**
|
||||
Insert a new element at the end of the queue.
|
||||
*/
|
||||
inline void pushBack(const T& e) {
|
||||
reserveSpace();
|
||||
|
||||
// Get the index of 1+tail
|
||||
int i = index(num);
|
||||
|
||||
// Initialize that element
|
||||
new (data + i)T(e);
|
||||
++num;
|
||||
}
|
||||
|
||||
/**
|
||||
pushBack
|
||||
*/
|
||||
inline void enqueue(const T& e) {
|
||||
pushBack(e);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Remove the last element from the queue. The queue will never
|
||||
shrink in size. (A typical queue only uses popFront).
|
||||
*/
|
||||
inline T popBack() {
|
||||
int tail = index(num - 1);
|
||||
T result(data[tail]);
|
||||
|
||||
// Call the destructor
|
||||
(data + tail)->~T();
|
||||
--num;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
Remove the next element from the head of the queue. The queue will never
|
||||
shrink in size. */
|
||||
inline T popFront() {
|
||||
T result(data[head]);
|
||||
// Call the destructor
|
||||
(data + head)->~T();
|
||||
head = (head + 1) % numAllocated;
|
||||
--num;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
popFront
|
||||
*/
|
||||
inline T dequeue() {
|
||||
return popFront();
|
||||
}
|
||||
|
||||
/**
|
||||
Removes all elements (invoking their destructors).
|
||||
|
||||
@param freeStorage If false, the underlying array is not deallocated
|
||||
(allowing fast push in the future), however, the size of the Queue
|
||||
is reported as zero.
|
||||
|
||||
*/
|
||||
void clear(bool freeStorage = true) {
|
||||
|
||||
FIND_ENDS;
|
||||
|
||||
// Invoke the destructors on the elements
|
||||
int i;
|
||||
for (i = head; i < firstEnd; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
|
||||
for (i = 0; i < secondEnd; ++i) {
|
||||
(data + i)->~T();
|
||||
}
|
||||
|
||||
num = 0;
|
||||
head = 0;
|
||||
if (freeStorage) {
|
||||
numAllocated = 0;
|
||||
System::free(data);
|
||||
data = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
/** Clear without freeing the underlying array. */
|
||||
void fastClear() {
|
||||
clear(false);
|
||||
}
|
||||
|
||||
/**
|
||||
Assignment operator.
|
||||
*/
|
||||
Queue& operator=(const Queue& other) {
|
||||
clear();
|
||||
_copy(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Number of elements in the queue.
|
||||
*/
|
||||
inline int size() const {
|
||||
return num;
|
||||
}
|
||||
|
||||
/**
|
||||
Number of elements in the queue.
|
||||
*/
|
||||
inline int length() const {
|
||||
return size();
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode
|
||||
*/
|
||||
inline T& operator[](int n) {
|
||||
debugAssert((n >= 0) && (n < num));
|
||||
return data[index(n)];
|
||||
}
|
||||
|
||||
/**
|
||||
Performs bounds checks in debug mode
|
||||
*/
|
||||
inline const T& operator[](int n) const {
|
||||
debugAssert((n >= 0) && (n < num));
|
||||
return data[index(n)];
|
||||
}
|
||||
|
||||
|
||||
/** Returns the back element */
|
||||
inline const T& last() const {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
inline T& last() {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
bool empty() const {
|
||||
return size() == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the given element is in the queue.
|
||||
*/
|
||||
bool contains(const T& e) const {
|
||||
for (int i = 0; i < size(); ++i) {
|
||||
if ((*this)[i] == e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
Calls delete on all objects[0...size-1]
|
||||
and sets the queue size to zero.
|
||||
*/
|
||||
void deleteAll() {
|
||||
FIND_ENDS;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < secondEnd; ++i) {
|
||||
delete data[i];
|
||||
}
|
||||
|
||||
for (i = head; i < firstEnd; ++i) {
|
||||
delete data[i];
|
||||
}
|
||||
clear();
|
||||
}
|
||||
};
|
||||
|
||||
#undef FIND_ENDS
|
||||
|
||||
}; // namespace
|
||||
|
||||
#endif
|
||||
164
dep/g3dlite/include/G3D/Random.h
Normal file
164
dep/g3dlite/include/G3D/Random.h
Normal file
@@ -0,0 +1,164 @@
|
||||
/**
|
||||
\file G3D/Random.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2009-01-02
|
||||
\edited 2012-07-20
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_Random_h
|
||||
#define G3D_Random_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/GMutex.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Random number generator.
|
||||
|
||||
Threadsafe.
|
||||
|
||||
Useful for generating consistent random numbers across platforms
|
||||
and when multiple threads are involved.
|
||||
|
||||
Uses the Fast Mersenne Twister (FMT-19937) algorithm.
|
||||
|
||||
On average, uniform() runs about 2x-3x faster than rand().
|
||||
|
||||
@cite http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/SFMT/index.html
|
||||
|
||||
On OS X, Random is about 10x faster than drand48() (which is
|
||||
threadsafe) and 4x faster than rand() (which is not threadsafe).
|
||||
|
||||
\sa Noise
|
||||
*/
|
||||
class Random {
|
||||
protected:
|
||||
|
||||
/** Constants (important for the algorithm; do not modify) */
|
||||
enum {
|
||||
N = 624,
|
||||
M = 397,
|
||||
R = 31,
|
||||
U = 11,
|
||||
S = 7,
|
||||
T = 15,
|
||||
L = 18,
|
||||
A = 0x9908B0DF,
|
||||
B = 0x9D2C5680,
|
||||
C = 0xEFC60000};
|
||||
|
||||
/**
|
||||
Prevents multiple overlapping calls to generate().
|
||||
*/
|
||||
Spinlock lock;
|
||||
|
||||
/** State vector (these are the next N values that will be returned) */
|
||||
uint32* state;
|
||||
|
||||
/** Index into state */
|
||||
int index;
|
||||
|
||||
bool m_threadsafe;
|
||||
|
||||
/** Generate the next N ints, and store them for readback later.
|
||||
Called from bits() */
|
||||
virtual void generate();
|
||||
|
||||
/** For subclasses. The void* parameter is just to distinguish this from the
|
||||
public constructor.*/
|
||||
Random(void*);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
Random& operator=(const Random&) {
|
||||
alwaysAssertM(false,
|
||||
"There is no copy constructor or assignment operator for Random because you "
|
||||
"probably didn't actually want to copy the state--it would "
|
||||
"be slow and duplicate the state of a pseudo-random sequence. Maybe you could "
|
||||
"provide arguments to a member variable in the constructor, "
|
||||
"or pass the Random by reference?");
|
||||
return *this;
|
||||
}
|
||||
|
||||
Random(const Random& r) {
|
||||
*this = r;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
/** \param threadsafe Set to false if you know that this random
|
||||
will only be used on a single thread. This eliminates the
|
||||
lock and improves performance on some platforms.
|
||||
*/
|
||||
Random(uint32 seed = 0xF018A4D2, bool threadsafe = true);
|
||||
|
||||
virtual ~Random();
|
||||
|
||||
virtual void reset(uint32 seed = 0xF018A4D2, bool threadsafe = true);
|
||||
|
||||
/** Each bit is random. Subclasses can choose to override just
|
||||
this method and the other methods will all work automatically. */
|
||||
virtual uint32 bits();
|
||||
|
||||
/** Uniform random integer on the range [min, max] */
|
||||
virtual int integer(int min, int max);
|
||||
|
||||
/** Uniform random float on the range [min, max] */
|
||||
virtual inline float uniform(float low, float high) {
|
||||
// We could compute the ratio in double precision here for
|
||||
// about 1.5x slower performance and slightly better
|
||||
// precision.
|
||||
return low + (high - low) * ((float)bits() / (float)0xFFFFFFFFUL);
|
||||
}
|
||||
|
||||
/** Uniform random float on the range [0, 1] */
|
||||
virtual inline float uniform() {
|
||||
// We could compute the ratio in double precision here for
|
||||
// about 1.5x slower performance and slightly better
|
||||
// precision.
|
||||
const float norm = 1.0f / (float)0xFFFFFFFFUL;
|
||||
return (float)bits() * norm;
|
||||
}
|
||||
|
||||
/** Normally distributed reals. */
|
||||
virtual float gaussian(float mean, float stdev);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to
|
||||
a cosine distribution about the positive z-axis. */
|
||||
virtual void cosHemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to
|
||||
a cosine distribution about the z-axis. */
|
||||
virtual void cosSphere(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors distributed according to a cosine
|
||||
power distribution (\f$ \cos^k \theta \f$) about
|
||||
the z-axis. */
|
||||
virtual void cosPowHemi(const float k, float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the
|
||||
hemisphere about the z-axis. */
|
||||
virtual void hemi(float& x, float& y, float& z);
|
||||
|
||||
/** Returns 3D unit vectors uniformly distributed on the sphere */
|
||||
virtual void sphere(float& x, float& y, float& z);
|
||||
|
||||
/**
|
||||
A shared instance for when the performance and features but not
|
||||
consistency of the class are desired. It is slightly (10%)
|
||||
faster to use a distinct instance than to use the common one.
|
||||
|
||||
Threadsafe.
|
||||
*/
|
||||
static Random& common();
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
380
dep/g3dlite/include/G3D/Ray.h
Normal file
380
dep/g3dlite/include/G3D/Ray.h
Normal file
@@ -0,0 +1,380 @@
|
||||
/**
|
||||
@file Ray.h
|
||||
|
||||
Ray class
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2002-07-12
|
||||
@edited 2009-06-29
|
||||
*/
|
||||
|
||||
#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:
|
||||
friend class Intersect;
|
||||
|
||||
Point3 m_origin;
|
||||
|
||||
/** Unit length */
|
||||
Vector3 m_direction;
|
||||
|
||||
/** 1.0 / direction */
|
||||
Vector3 m_invDirection;
|
||||
|
||||
|
||||
/** The following are for the "ray slope" optimization from
|
||||
"Fast Ray / Axis-Aligned Bounding Box Overlap Tests using Ray Slopes"
|
||||
by Martin Eisemann, Thorsten Grosch, Stefan M<><4D>ller and Marcus Magnor
|
||||
Computer Graphics Lab, TU Braunschweig, Germany and
|
||||
University of Koblenz-Landau, Germany */
|
||||
enum Classification {MMM, MMP, MPM, MPP, PMM, PMP, PPM, PPP, POO, MOO, OPO, OMO, OOP, OOM, OMM, OMP, OPM, OPP, MOM, MOP, POM, POP, MMO, MPO, PMO, PPO};
|
||||
|
||||
Classification classification;
|
||||
|
||||
/** ray slope */
|
||||
float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi;
|
||||
|
||||
/** Precomputed components */
|
||||
float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy;
|
||||
|
||||
public:
|
||||
/** \param direction Assumed to have unit length */
|
||||
void set(const Point3& origin, const Vector3& direction);
|
||||
|
||||
const Point3& origin() const {
|
||||
return m_origin;
|
||||
}
|
||||
|
||||
/** Unit direction vector. */
|
||||
const Vector3& direction() const {
|
||||
return m_direction;
|
||||
}
|
||||
|
||||
/** Component-wise inverse of direction vector. May have inf() components */
|
||||
const Vector3& invDirection() const {
|
||||
return m_invDirection;
|
||||
}
|
||||
|
||||
Ray() {
|
||||
set(Point3::zero(), Vector3::unitX());
|
||||
}
|
||||
|
||||
/** \param direction Assumed to have unit length */
|
||||
Ray(const Point3& origin, const Vector3& direction) {
|
||||
set(origin, direction);
|
||||
}
|
||||
|
||||
Ray(class BinaryInput& b);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/**
|
||||
Creates a Ray from a origin and a (nonzero) unit direction.
|
||||
*/
|
||||
static Ray fromOriginAndDirection(const Point3& point, const Vector3& direction) {
|
||||
return Ray(point, direction);
|
||||
}
|
||||
|
||||
/** Returns a new ray which has the same direction but an origin
|
||||
advanced along direction by @a distance */
|
||||
Ray bumpedRay(float distance) const {
|
||||
return Ray(m_origin + m_direction * distance, m_direction);
|
||||
}
|
||||
|
||||
/** Returns a new ray which has the same direction but an origin
|
||||
advanced by \a distance * \a bumpDirection */
|
||||
Ray bumpedRay(float distance, const Vector3& bumpDirection) const {
|
||||
return Ray(m_origin + bumpDirection * distance, m_direction);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Returns the closest point on the Ray to point.
|
||||
*/
|
||||
Point3 closestPoint(const Point3& point) const {
|
||||
float t = m_direction.dot(point - m_origin);
|
||||
if (t < 0) {
|
||||
return m_origin;
|
||||
} else {
|
||||
return m_origin + m_direction * t;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the closest distance between point and the Ray
|
||||
*/
|
||||
float distance(const Point3& 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.
|
||||
*/
|
||||
Point3 intersection(const class Plane& plane) const;
|
||||
|
||||
/**
|
||||
Returns the distance until intersection with the sphere or the (solid) ball bounded by the 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.
|
||||
|
||||
\param solid If true, rays inside the sphere immediately intersect (good for collision detection). If false, they hit the opposite side of the sphere (good for ray tracing).
|
||||
*/
|
||||
float intersectionTime(const class Sphere& sphere, bool solid = false) 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,
|
||||
float& w0, float& w1, float& 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
|
||||
*/
|
||||
float intersectionTime(
|
||||
const Point3& vert0,
|
||||
const Point3& vert1,
|
||||
const Point3& vert2,
|
||||
const Vector3& edge01,
|
||||
const Vector3& edge02) const;
|
||||
|
||||
|
||||
float intersectionTime(
|
||||
const Point3& vert0,
|
||||
const Point3& vert1,
|
||||
const Point3& vert2) const {
|
||||
|
||||
return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0);
|
||||
}
|
||||
|
||||
|
||||
float intersectionTime(
|
||||
const Point3& vert0,
|
||||
const Point3& vert1,
|
||||
const Point3& vert2,
|
||||
float& w0,
|
||||
float& w1,
|
||||
float& w2) const {
|
||||
|
||||
return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0, w0, w1, w2);
|
||||
}
|
||||
|
||||
|
||||
/* One-sided triangle
|
||||
*/
|
||||
float intersectionTime(const Triangle& triangle) const {
|
||||
return intersectionTime(
|
||||
triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
|
||||
triangle.edge01(), triangle.edge02());
|
||||
}
|
||||
|
||||
|
||||
float intersectionTime
|
||||
(const Triangle& triangle,
|
||||
float& w0,
|
||||
float& w1,
|
||||
float& 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 Point3& vert0,
|
||||
const Point3& vert1,
|
||||
const Point3& 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, m_direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return finf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, m_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 finf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(m_direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return finf();
|
||||
}
|
||||
|
||||
|
||||
// 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 finf();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
inline float Ray::intersectionTime
|
||||
(const Point3& vert0,
|
||||
const Point3& vert1,
|
||||
const Point3& vert2,
|
||||
const Vector3& edge1,
|
||||
const Vector3& edge2,
|
||||
float& w0,
|
||||
float& w1,
|
||||
float& 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, m_direction, edge2);
|
||||
|
||||
// if determinant is near zero, ray lies in plane of triangle
|
||||
const float det = DOT(edge1, pvec);
|
||||
|
||||
if (det < EPSILON) {
|
||||
return finf();
|
||||
}
|
||||
|
||||
// calculate distance from vert0 to ray origin
|
||||
SUB(tvec, m_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 finf();
|
||||
}
|
||||
|
||||
// prepare to test V parameter
|
||||
CROSS(qvec, tvec, edge1);
|
||||
|
||||
// calculate V parameter and test bounds
|
||||
v = DOT(m_direction, qvec);
|
||||
if ((v < 0.0f) || (u + v > det)) {
|
||||
// Hit the plane outside the triangle
|
||||
return finf();
|
||||
}
|
||||
|
||||
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 finf();
|
||||
}
|
||||
}
|
||||
|
||||
#undef EPSILON
|
||||
#undef CROSS
|
||||
#undef DOT
|
||||
#undef SUB
|
||||
|
||||
}// namespace
|
||||
|
||||
#endif
|
||||
472
dep/g3dlite/include/G3D/Rect2D.h
Normal file
472
dep/g3dlite/include/G3D/Rect2D.h
Normal file
@@ -0,0 +1,472 @@
|
||||
/**
|
||||
\file Rect2D.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2003-11-13
|
||||
\created 2011-06-16
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Rect2D_h
|
||||
#define G3D_Rect2D_h
|
||||
|
||||
// Linux defines this as a macro
|
||||
#ifdef border
|
||||
#undef border
|
||||
#endif
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Vector2.h"
|
||||
|
||||
#ifdef _MSC_VER
|
||||
// Turn off "conditional expression is constant" warning; MSVC generates this
|
||||
// for debug assertions in inlined methods.
|
||||
# pragma warning (disable : 4127)
|
||||
#endif
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
|
||||
/**
|
||||
If you are using this class for pixel rectangles, keep in mind that the last
|
||||
pixel you can draw to is at x0() + width() - 1.
|
||||
*/
|
||||
class Rect2D {
|
||||
private:
|
||||
Point2 min, max;
|
||||
|
||||
/**
|
||||
Returns true if the whole polygon is clipped.
|
||||
@param p Value of the point
|
||||
@param axis Index [0 or 1] of the axis to clip along?
|
||||
@param clipGreater Are we clipping greater than or less than the line?
|
||||
@param inPoly Polygon being clipped
|
||||
@param outPoly The clipped polygon
|
||||
*/
|
||||
template<class T>
|
||||
static bool clipSide2D(
|
||||
const float p, bool clipGreater, int axis,
|
||||
const Array<T>& inPoly, Array<T>& outPoly) {
|
||||
|
||||
outPoly.clear();
|
||||
int i0 = -1;
|
||||
|
||||
Vector2 pt1;
|
||||
bool c1 = true;
|
||||
|
||||
float negate = clipGreater ? -1 : 1;
|
||||
|
||||
// Find a point that is not clipped
|
||||
for (i0 = 0; (i0 < inPoly.length()) && c1; ++i0) {
|
||||
pt1 = inPoly[i0];
|
||||
c1 = (negate * pt1[axis]) < (negate * p);
|
||||
}
|
||||
|
||||
// We incremented i0 one time to many
|
||||
--i0;
|
||||
|
||||
if (c1) {
|
||||
// We could not find an unclipped point
|
||||
return true;
|
||||
}
|
||||
|
||||
outPoly.append(pt1);
|
||||
|
||||
// for each point in inPoly,
|
||||
// if the point is outside the side and the previous one was also outside, continue
|
||||
// if the point is outside the side and the previous one was inside, cut the line
|
||||
// if the point is inside the side and the previous one was also inside, append the points
|
||||
// if the point is inside the side and the previous one was outside, cut the line
|
||||
for (int i = 1; i <= inPoly.length(); ++i) {
|
||||
T pt2 = inPoly[(i + i0) % inPoly.length()];
|
||||
bool c2 = (negate * pt2[axis]) < (negate * p);
|
||||
|
||||
if (c1 ^ c2) {
|
||||
|
||||
if (!c1 && c2 && (i > 1)) {
|
||||
// Unclipped to clipped trasition and not the first iteration
|
||||
outPoly.append(pt1);
|
||||
}
|
||||
|
||||
// only one point is clipped, find where the line crosses the clipping plane
|
||||
|
||||
|
||||
float alpha;
|
||||
if (pt2[axis] == pt1[axis]) {
|
||||
alpha = 0;
|
||||
} else {
|
||||
alpha = (p - pt1[axis]) / (pt2[axis] - pt1[axis]);
|
||||
}
|
||||
outPoly.append(pt1.lerp(pt2, alpha));
|
||||
} else if (! (c1 || c2) && (i != 1)) {
|
||||
// neither point is clipped (don't do this the first time
|
||||
// because we appended the first pt before the loop)
|
||||
outPoly.append(pt1);
|
||||
}
|
||||
|
||||
pt1 = pt2;
|
||||
c1 = c2;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Uninitialized constructor */
|
||||
Rect2D(bool b) {}
|
||||
public:
|
||||
|
||||
/** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/
|
||||
Rect2D(const Any& any);
|
||||
|
||||
/** Converts the Rect2D to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
Rect2D(const Rect2D& r) : min(r.min), max(r.max) {}
|
||||
|
||||
/** Creates the empty set rectangle.
|
||||
*/
|
||||
Rect2D() : min(fnan(), fnan()), max(fnan(), fnan()) {}
|
||||
|
||||
static const Rect2D& empty();
|
||||
|
||||
/** Returns true if this is the empty set, which is distinct from a zero-area rectangle. */
|
||||
inline bool isEmpty() const {
|
||||
return min.isNaN() && max.isNaN();
|
||||
}
|
||||
|
||||
/** Creates a rectangle at 0,0 with the given width and height*/
|
||||
Rect2D(const Vector2& wh) : min(0, 0), max(wh.x, wh.y) {}
|
||||
|
||||
Vector2 extent() const {
|
||||
if (isEmpty()) {
|
||||
return Vector2::zero();
|
||||
} else {
|
||||
return max - min;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Uniformly random point on the interior */
|
||||
Point2 randomPoint() const {
|
||||
return Point2(uniformRandom(0, max.x - min.x) + min.x,
|
||||
uniformRandom(0, max.y - min.y) + min.y);
|
||||
}
|
||||
|
||||
float width() const {
|
||||
if (isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return max.x - min.x;
|
||||
}
|
||||
}
|
||||
|
||||
float height() const {
|
||||
if (isEmpty()) {
|
||||
return 0;
|
||||
} else {
|
||||
return max.y - min.y;
|
||||
}
|
||||
}
|
||||
|
||||
float x0() const {
|
||||
return min.x;
|
||||
}
|
||||
|
||||
float x1() const {
|
||||
return max.x;
|
||||
}
|
||||
|
||||
float y0() const {
|
||||
return min.y;
|
||||
}
|
||||
|
||||
float y1() const {
|
||||
return max.y;
|
||||
}
|
||||
|
||||
/** Min, min corner */
|
||||
Point2 x0y0() const {
|
||||
return min;
|
||||
}
|
||||
|
||||
Point2 x1y0() const {
|
||||
return Point2(max.x, min.y);
|
||||
}
|
||||
|
||||
Point2 x0y1() const {
|
||||
return Point2(min.x, max.y);
|
||||
}
|
||||
|
||||
/** Max,max corner */
|
||||
Point2 x1y1() const {
|
||||
return max;
|
||||
}
|
||||
|
||||
/** Width and height */
|
||||
Vector2 wh() const {
|
||||
if (isEmpty()) {
|
||||
return Vector2::zero();
|
||||
} else {
|
||||
return max - min;
|
||||
}
|
||||
}
|
||||
|
||||
Point2 center() const {
|
||||
return (max + min) * 0.5;
|
||||
}
|
||||
|
||||
float area() const {
|
||||
return width() * height();
|
||||
}
|
||||
|
||||
bool isFinite() const {
|
||||
return (min.isFinite() && max.isFinite());
|
||||
}
|
||||
|
||||
Rect2D lerp(const Rect2D& other, float alpha) const {
|
||||
Rect2D out(false);
|
||||
|
||||
out.min = min.lerp(other.min, alpha);
|
||||
out.max = max.lerp(other.max, alpha);
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static Rect2D xyxy(float x0, float y0, float x1, float y1) {
|
||||
Rect2D r(false);
|
||||
|
||||
r.min.x = G3D::min(x0, x1);
|
||||
r.min.y = G3D::min(y0, y1);
|
||||
r.max.x = G3D::max(x0, x1);
|
||||
r.max.y = G3D::max(y0, y1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static Rect2D xyxy(const Point2& v0, const Point2& v1) {
|
||||
Rect2D r(false);
|
||||
|
||||
r.min = v0.min(v1);
|
||||
r.max = v0.max(v1);
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
static Rect2D xywh(float x, float y, float w, float h) {
|
||||
return xyxy(x, y, x + w, y + h);
|
||||
}
|
||||
|
||||
static Rect2D xywh(const Point2& v, const Vector2& w) {
|
||||
return xyxy(v.x, v.y, v.x + w.x, v.y + w.y);
|
||||
}
|
||||
|
||||
/** Constructs a Rect2D with infinite boundaries.
|
||||
Use isFinite() to test either min or max.
|
||||
*/
|
||||
static Rect2D inf() {
|
||||
return xyxy(Vector2::inf(), Vector2::inf());
|
||||
}
|
||||
|
||||
bool contains(const Point2& v) const {
|
||||
// This will automatically return false if isEmpty()
|
||||
return (v.x >= min.x) && (v.y >= min.y) && (v.x <= max.x) && (v.y <= max.y);
|
||||
}
|
||||
|
||||
bool contains(const Rect2D& r) const {
|
||||
// This will automatically return false if isEmpty()
|
||||
return (min.x <= r.min.x) && (min.y <= r.min.y) &&
|
||||
(max.x >= r.max.x) && (max.y >= r.max.y);
|
||||
}
|
||||
|
||||
/** True if there is non-zero area to the intersection between @a this and @a r.
|
||||
Note that two rectangles that are adjacent do not intersect because there is
|
||||
zero area to the overlap, even though one of them "contains" the corners of the other.*/
|
||||
bool intersects(const Rect2D& r) const {
|
||||
// This will automatically return false if isEmpty()
|
||||
return (min.x < r.max.x) && (min.y < r.max.y) &&
|
||||
(max.x > r.min.x) && (max.y > r.min.y);
|
||||
}
|
||||
|
||||
/** Like intersection, but counts the adjacent case as touching. */
|
||||
bool intersectsOrTouches(const Rect2D& r) const {
|
||||
// This will automatically return false if isEmpty()
|
||||
return (min.x <= r.max.x) && (min.y <= r.max.y) &&
|
||||
(max.x >= r.min.x) && (max.y >= r.min.y);
|
||||
}
|
||||
|
||||
Rect2D operator*(float s) const {
|
||||
return xyxy(min.x * s, min.y * s, max.x * s, max.y * s);
|
||||
}
|
||||
|
||||
Rect2D operator*(const Vector2& s) const {
|
||||
return xyxy(min * s, max * s);
|
||||
}
|
||||
|
||||
Rect2D operator/(float s) const {
|
||||
return xyxy(min / s, max / s);
|
||||
}
|
||||
|
||||
Rect2D operator/(const Vector2& s) const {
|
||||
return xyxy(min / s, max / s);
|
||||
}
|
||||
|
||||
Rect2D operator+(const Vector2& v) const {
|
||||
return xyxy(min + v, max + v);
|
||||
}
|
||||
|
||||
Rect2D operator-(const Vector2& v) const {
|
||||
return xyxy(min - v, max - v);
|
||||
}
|
||||
|
||||
bool operator==(const Rect2D& other) const {
|
||||
return (min == other.min) && (max == other.max);
|
||||
}
|
||||
|
||||
bool operator!=(const Rect2D& other) const {
|
||||
return (min != other.min) || (max != other.max);
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** Returns the corners in the order: (min,min), (max,min), (max,max), (min,max). */
|
||||
Point2 corner(int i) const {
|
||||
debugAssert(i >= 0 && i < 4);
|
||||
switch (i & 3) {
|
||||
case 0:
|
||||
return Point2(min.x, min.y);
|
||||
case 1:
|
||||
return Point2(max.x, min.y);
|
||||
case 2:
|
||||
return Point2(max.x, max.y);
|
||||
case 3:
|
||||
return Point2(min.x, max.y);
|
||||
default:
|
||||
// Should never get here
|
||||
return Point2(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @deprecated
|
||||
@sa expand() */
|
||||
Rect2D border(float delta) const {
|
||||
return Rect2D::xywh(x0() + delta,
|
||||
y0() + delta,
|
||||
width() - 2.0f * delta,
|
||||
height() - 2.0f * delta);
|
||||
}
|
||||
|
||||
/** Returns a new Rect2D that is bigger/smaller by the specified amount
|
||||
(negative is shrink.) */
|
||||
Rect2D expand(float delta) const {
|
||||
float newX = x0() - delta;
|
||||
float newY = y0() - delta;
|
||||
float newW = width() + 2.0f * delta;
|
||||
float newH = height() + 2.0f * delta;
|
||||
|
||||
if (newW < 0.0f) {
|
||||
newX = (x0() + width()) / 2.0f;
|
||||
newW = 0.0f;
|
||||
}
|
||||
|
||||
if (newH < 0.0f) {
|
||||
newY = (y0() + height()) / 2.0f;
|
||||
newH = 0.0f;
|
||||
}
|
||||
return Rect2D::xywh(newX, newY, newW, newH);
|
||||
}
|
||||
|
||||
void merge(const Rect2D& other) {
|
||||
if (isEmpty()) {
|
||||
*this = other;
|
||||
} else if (! other.isEmpty()) {
|
||||
min = min.min(other.min);
|
||||
max = max.max(other.max);
|
||||
}
|
||||
}
|
||||
|
||||
/** Computes a rectangle that contains both @a a and @a b.
|
||||
Note that even if @a or @b has zero area, its origin will be included.*/
|
||||
Rect2D(const Rect2D& a, const Rect2D& b) {
|
||||
*this = a;
|
||||
merge(b);
|
||||
}
|
||||
|
||||
/**
|
||||
Clips so that the rightmost point of the outPoly is at rect.x1 (e.g. a 800x600 window produces
|
||||
rightmost point 799, not 800). The results are suitable for pixel rendering if iRounded.
|
||||
Templated so that it will work for Vector2,3,4 (the z and w components are interpolated linearly).
|
||||
The template parameter must define T.lerp and contain x and y components.
|
||||
|
||||
If the entire polygon is clipped by a single side, the result will be empty.
|
||||
The result might also have zero area but not be empty.
|
||||
*/
|
||||
template<class T>
|
||||
void clip(const Array<T>& inPoly, Array<T>& outPoly) const {
|
||||
|
||||
const bool greaterThan = true;
|
||||
const bool lessThan = false;
|
||||
const int X = 0;
|
||||
const int Y = 1;
|
||||
|
||||
Array<T> temp;
|
||||
|
||||
bool entirelyClipped =
|
||||
clipSide2D(x0(), lessThan, X, inPoly, temp) ||
|
||||
clipSide2D(x1(), greaterThan, X, temp, outPoly) ||
|
||||
clipSide2D(y0(), lessThan, Y, outPoly, temp) ||
|
||||
clipSide2D(y1(), greaterThan, Y, temp, outPoly);
|
||||
|
||||
if (entirelyClipped) {
|
||||
outPoly.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** Returns the largest, centered Rect2D that can fit inside this
|
||||
while maintaining the aspect ratio of x:y. Convenient for
|
||||
displaying images in odd-shaped windows.
|
||||
*/
|
||||
Rect2D largestCenteredSubRect(float ww, float hh) const {
|
||||
float textureAspect = hh / ww;
|
||||
float viewAspect = height() / width();
|
||||
|
||||
if (viewAspect > textureAspect) {
|
||||
// The view is too tall
|
||||
float h = width() * textureAspect;
|
||||
float y = (height() - h) / 2;
|
||||
return Rect2D::xywh(0, y, width(), h) + corner(0);
|
||||
} else {
|
||||
// The view is too wide
|
||||
float w = height() / textureAspect;
|
||||
float x = (width() - w) / 2;
|
||||
return Rect2D::xywh(x, 0, w, height()) + corner(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the overlap region between the two rectangles. This may
|
||||
have zero area if they do not intersect. See the two-Rect2D
|
||||
constructor and merge() for a way to compute a union-like
|
||||
rectangle.
|
||||
*/
|
||||
Rect2D intersect(const Rect2D& other) const {
|
||||
if (intersects(other)) {
|
||||
return Rect2D::xyxy(min.max(other.min), max.min(other.max));
|
||||
} else {
|
||||
return empty();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
typedef Rect2D AABox2D;
|
||||
}
|
||||
|
||||
#endif
|
||||
56
dep/g3dlite/include/G3D/ReferenceCount.h
Normal file
56
dep/g3dlite/include/G3D/ReferenceCount.h
Normal file
@@ -0,0 +1,56 @@
|
||||
/**
|
||||
\file G3D/ReferenceCount.h
|
||||
|
||||
Reference Counting Garbage Collector for C++
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-10-23
|
||||
\edited 2013-01-05
|
||||
*/
|
||||
#ifndef G3D_ReferenceCount_h
|
||||
#define G3D_ReferenceCount_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/debug.h"
|
||||
#include "G3D/AtomicInt32.h"
|
||||
|
||||
#define USE_SHARED_PTR
|
||||
|
||||
#define ReferenceCountedPointer shared_ptr
|
||||
#define WeakReferenceCountedPointer weak_ptr
|
||||
namespace G3D {
|
||||
|
||||
class ReferenceCountedObject : public enable_shared_from_this<ReferenceCountedObject> {
|
||||
public:
|
||||
virtual ~ReferenceCountedObject() {};
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
namespace G3D {
|
||||
|
||||
template<class T>
|
||||
bool isNull(const ReferenceCountedPointer<T>& ptr) {
|
||||
return ! ptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool notNull(const ReferenceCountedPointer<T>& ptr) {
|
||||
return (bool)ptr;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool isNull(const T* ptr) {
|
||||
return ptr == NULL;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
bool notNull(const T* ptr) {
|
||||
return ptr != NULL;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
97
dep/g3dlite/include/G3D/RegistryUtil.h
Normal file
97
dep/g3dlite/include/G3D/RegistryUtil.h
Normal file
@@ -0,0 +1,97 @@
|
||||
/**
|
||||
@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_WINDOWS
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Provides generalized Windows registry querying.
|
||||
|
||||
All key names are one string in the format:
|
||||
"[base key]\[sub-keys]"
|
||||
|
||||
A value must now be provided for every query.
|
||||
An empty value string will use the (Default) 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
|
||||
|
||||
valueExists() should be used to validate a key+value before reading or writing
|
||||
to ensure that a debug assert or false return is for a different error during
|
||||
reads and writes.
|
||||
|
||||
All read and write calls will assert when a key will not open for reasons other
|
||||
that it does not exist. All read and write calls will assert when the value cannot
|
||||
be read or written for any reason.
|
||||
*/
|
||||
class RegistryUtil {
|
||||
|
||||
public:
|
||||
/** returns true if the key exists and the current user has permission to read */
|
||||
static bool keyExists(const std::string& key);
|
||||
|
||||
/** returns true if the key exists and the current user has permission to read */
|
||||
static bool valueExists(const std::string& key, const std::string& value);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readInt32(const std::string& key, const std::string& value, int32& data);
|
||||
|
||||
/**
|
||||
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 data pointer to the output buffer of sufficient size. Pass NULL as data in order to have available data size returned in dataSize.
|
||||
@param dataSize size of the output buffer. When NULL is passed for data, contains the size of available data on successful return.
|
||||
*/
|
||||
static bool readBytes(const std::string& key, const std::string& value, uint8* data, uint32& dataSize);
|
||||
|
||||
/** returns false if the key could not be read for any reason. */
|
||||
static bool readString(const std::string& key, const std::string& value, std::string& data);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeInt32(const std::string& key, const std::string& value, int32 data);
|
||||
|
||||
/**
|
||||
Writes an arbitrary amount of data to a binary registry key.
|
||||
returns false if the key could not be written for any reason.
|
||||
|
||||
@param data pointer to the input buffer
|
||||
@param dataSize size of the input buffer that should be written
|
||||
*/
|
||||
static bool writeBytes(const std::string& key, const std::string& value, const uint8* data, uint32 dataSize);
|
||||
|
||||
/** returns false if the key could not be written for any reason. */
|
||||
static bool writeString(const std::string& key, const std::string& value, const std::string& data);
|
||||
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif // G3D_WINDOWS
|
||||
|
||||
#endif // G3D_REGISTRYTUIL_H
|
||||
194
dep/g3dlite/include/G3D/Set.h
Normal file
194
dep/g3dlite/include/G3D/Set.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/**
|
||||
@file Set.h
|
||||
|
||||
Hash set
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2001-12-09
|
||||
@edited 2009-06-10
|
||||
*/
|
||||
|
||||
#ifndef G3D_Set_h
|
||||
#define G3D_Set_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
#include <assert.h>
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
An unordered data structure that has at most one of each element.
|
||||
Provides O(1) time insert, remove, and member test (contains).
|
||||
|
||||
Set uses G3D::Table internally, which means that the template type T
|
||||
must define a hashCode and operator== function. See G3D::Table for
|
||||
a discussion of these functions.
|
||||
*/
|
||||
// There is not copy constructor or assignment operator defined because
|
||||
// the default ones are correct for Set.
|
||||
template<class T, class HashFunc = HashTrait<T>, class EqualsFunc = EqualsTrait<T> >
|
||||
class Set {
|
||||
|
||||
/**
|
||||
If an object is a member, it is contained in
|
||||
this table.
|
||||
*/
|
||||
Table<T, bool, HashFunc, EqualsFunc> memberTable;
|
||||
|
||||
public:
|
||||
|
||||
void clearAndSetMemoryManager(const MemoryManager::Ref& m) {
|
||||
memberTable.clearAndSetMemoryManager(m);
|
||||
}
|
||||
|
||||
virtual ~Set() {}
|
||||
|
||||
int size() const {
|
||||
return (int)memberTable.size();
|
||||
}
|
||||
|
||||
bool contains(const T& member) const {
|
||||
return memberTable.containsKey(member);
|
||||
}
|
||||
|
||||
/**
|
||||
Inserts into the table if not already present.
|
||||
Returns true if this is the first time the element was added.
|
||||
*/
|
||||
bool insert(const T& member) {
|
||||
bool isNew = false;
|
||||
memberTable.getCreate(member, isNew) = true;
|
||||
return isNew;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns true if the element was present and removed. Returns false
|
||||
if the element was not present.
|
||||
*/
|
||||
bool remove(const T& member) {
|
||||
return memberTable.remove(member);
|
||||
}
|
||||
|
||||
/** If @a member is present, sets @a removed to the element
|
||||
being removed and returns true. Otherwise returns false
|
||||
and does not write to @a removed. This is useful when building
|
||||
efficient hashed data structures that wrap Set.
|
||||
*/
|
||||
bool getRemove(const T& member, T& removed) {
|
||||
bool ignore;
|
||||
return memberTable.getRemove(member, removed, ignore);
|
||||
}
|
||||
|
||||
/** If a value that is EqualsFunc to @a member is present, returns a pointer to the
|
||||
version stored in the data structure, otherwise returns NULL.
|
||||
*/
|
||||
const T* getPointer(const T& member) const {
|
||||
return memberTable.getKeyPointer(member);
|
||||
}
|
||||
|
||||
Array<T> getMembers() const {
|
||||
return memberTable.getKeys();
|
||||
}
|
||||
|
||||
void getMembers(Array<T>& keyArray) const {
|
||||
memberTable.getKeys(keyArray);
|
||||
}
|
||||
|
||||
void clear() {
|
||||
memberTable.clear();
|
||||
}
|
||||
|
||||
void deleteAll() {
|
||||
getMembers().deleteAll();
|
||||
clear();
|
||||
}
|
||||
|
||||
/**
|
||||
C++ STL style iterator variable. See begin().
|
||||
*/
|
||||
class Iterator {
|
||||
private:
|
||||
friend class Set<T>;
|
||||
|
||||
// Note: this is a Table iterator, we are currently defining
|
||||
// Set iterator
|
||||
typename Table<T, bool>::Iterator it;
|
||||
|
||||
Iterator(const typename Table<T, bool>::Iterator& it) : it(it) {}
|
||||
|
||||
public:
|
||||
inline bool operator!=(const Iterator& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
bool isValid() const {
|
||||
return it.isValid();
|
||||
}
|
||||
|
||||
/** @deprecated Use isValid */
|
||||
bool hasMore() const {
|
||||
return it.isValid();
|
||||
}
|
||||
|
||||
bool operator==(const Iterator& other) const {
|
||||
return it == other.it;
|
||||
}
|
||||
|
||||
/**
|
||||
Pre increment.
|
||||
*/
|
||||
Iterator& operator++() {
|
||||
++it;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
Post increment (slower than preincrement).
|
||||
*/
|
||||
Iterator operator++(int) {
|
||||
Iterator old = *this;
|
||||
++(*this);
|
||||
return old;
|
||||
}
|
||||
|
||||
const T& operator*() const {
|
||||
return it->key;
|
||||
}
|
||||
|
||||
T* operator->() const {
|
||||
return &(it->key);
|
||||
}
|
||||
|
||||
operator T*() const {
|
||||
return &(it->key);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns the first member.
|
||||
Use preincrement (++entry) to get to the next element.
|
||||
Do not modify the set while iterating.
|
||||
*/
|
||||
Iterator begin() const {
|
||||
return Iterator(memberTable.begin());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
C++ STL style iterator method. Returns one after the last iterator
|
||||
element.
|
||||
*/
|
||||
const Iterator end() const {
|
||||
return Iterator(memberTable.end());
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
190
dep/g3dlite/include/G3D/SmallArray.h
Normal file
190
dep/g3dlite/include/G3D/SmallArray.h
Normal file
@@ -0,0 +1,190 @@
|
||||
/**
|
||||
\file G3D/SmallArray.h
|
||||
|
||||
\created 2009-04-26
|
||||
\edited 2012-07-23
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire, http://graphics.cs.williams.edu
|
||||
All rights reserved.
|
||||
*/
|
||||
#ifndef G3D_SmallArray_h
|
||||
#define G3D_SmallArray_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/MemoryManager.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Embeds \a N elements to reduce allocation time and increase
|
||||
memory coherence when working with arrays of arrays.
|
||||
Offers a limited subset of the functionality of G3D::Array.*/
|
||||
template<class T, int N>
|
||||
class SmallArray {
|
||||
private:
|
||||
int m_size;
|
||||
|
||||
/** First N elements */
|
||||
T m_embedded[N];
|
||||
|
||||
/** Remaining elements */
|
||||
Array<T> m_rest;
|
||||
|
||||
public:
|
||||
|
||||
SmallArray() : m_size(0) {}
|
||||
|
||||
inline int size() const {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
void resize(int n, bool shrinkIfNecessary = true) {
|
||||
m_rest.resize(std::max(0, n - N), shrinkIfNecessary);
|
||||
m_size = n;
|
||||
}
|
||||
|
||||
void clear(bool shrinkIfNecessary = true) {
|
||||
resize(0, shrinkIfNecessary);
|
||||
}
|
||||
|
||||
void clearAndSetMemoryManager(MemoryManager::Ref& m) {
|
||||
clear();
|
||||
m_rest.clearAndSetMemoryManager(m);
|
||||
}
|
||||
|
||||
inline T& operator[](int i) {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
return m_embedded[i];
|
||||
} else {
|
||||
return m_rest[i - N];
|
||||
}
|
||||
}
|
||||
|
||||
inline const T& operator[](int i) const {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
return m_embedded[i];
|
||||
} else {
|
||||
return m_rest[i - N];
|
||||
}
|
||||
}
|
||||
|
||||
inline void push(const T& v) {
|
||||
++m_size;
|
||||
if (m_size <= N) {
|
||||
m_embedded[m_size - 1] = v;
|
||||
} else {
|
||||
m_rest.append(v);
|
||||
}
|
||||
}
|
||||
|
||||
inline void append(const T& v) {
|
||||
push(v);
|
||||
}
|
||||
|
||||
inline void append(const T& v, const T& v2) {
|
||||
push(v);
|
||||
push(v2);
|
||||
}
|
||||
|
||||
inline void append(const T& v, const T& v2, const T& v3) {
|
||||
push(v);
|
||||
push(v2);
|
||||
push(v3);
|
||||
}
|
||||
|
||||
inline void append(const T& v, const T& v2, const T& v3, const T& v4) {
|
||||
push(v);
|
||||
push(v2);
|
||||
push(v3);
|
||||
push(v4);
|
||||
}
|
||||
|
||||
/** Find the index of \a v or -1 if not found */
|
||||
int findIndex(const T& v) {
|
||||
for (int i = 0; i < N; ++i) {
|
||||
if (m_embedded[i] == v) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return m_rest.findIndex(v) + N;
|
||||
}
|
||||
|
||||
void fastRemove(int i, bool shrinkIfNecessary = false) {
|
||||
debugAssert(i < m_size && i >= 0);
|
||||
if (i < N) {
|
||||
if (m_size <= N) {
|
||||
// Exclusively embedded
|
||||
m_embedded[i] = m_embedded[m_size - 1];
|
||||
} else {
|
||||
// Move one down from the rest array
|
||||
m_embedded[i] = m_rest.pop();
|
||||
}
|
||||
} else {
|
||||
// Removing from the rest array
|
||||
m_rest.fastRemove(i - N, shrinkIfNecessary);
|
||||
}
|
||||
--m_size;
|
||||
}
|
||||
|
||||
T pop() {
|
||||
debugAssert(m_size > 0);
|
||||
if (m_size <= N) {
|
||||
// Popping from embedded, don't need a temporary
|
||||
--m_size;
|
||||
return m_embedded[m_size];
|
||||
} else {
|
||||
// Popping from rest
|
||||
--m_size;
|
||||
return m_rest.pop();
|
||||
}
|
||||
}
|
||||
|
||||
inline void popDiscard() {
|
||||
debugAssert(m_size > 0);
|
||||
if (m_size > N) {
|
||||
m_rest.popDiscard();
|
||||
}
|
||||
--m_size;
|
||||
}
|
||||
|
||||
inline T& next() {
|
||||
++m_size;
|
||||
if (m_size <= N) {
|
||||
return m_embedded[m_size - 1];
|
||||
} else {
|
||||
return m_rest.next();
|
||||
}
|
||||
}
|
||||
|
||||
bool contains(const T& value) const {
|
||||
for (int i = std::min(m_size, N) - 1; i >= 0; --i) {
|
||||
if (m_embedded[i] == value) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return m_rest.contains(value);
|
||||
}
|
||||
|
||||
template<int MIN_ELEMENTS>
|
||||
SmallArray<T, N>& operator=(const Array<T, MIN_ELEMENTS>& src) {
|
||||
resize(src.size());
|
||||
for (int i = 0; i < src.size(); ++i) {
|
||||
(*this)[i] = src[i];
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline const T& last() const {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
|
||||
inline T& last() {
|
||||
return (*this)[size() - 1];
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
#endif
|
||||
6
dep/g3dlite/include/G3D/SpawnBehavior.h
Normal file
6
dep/g3dlite/include/G3D/SpawnBehavior.h
Normal file
@@ -0,0 +1,6 @@
|
||||
#ifndef SpawnBehavior_h
|
||||
#define SpawnBehavior_h
|
||||
namespace G3D {
|
||||
enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD};
|
||||
}
|
||||
#endif
|
||||
155
dep/g3dlite/include/G3D/Sphere.h
Normal file
155
dep/g3dlite/include/G3D/Sphere.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/**
|
||||
\file G3D/Sphere.h
|
||||
|
||||
Sphere class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-06-02
|
||||
\edited 2011-02-07
|
||||
*/
|
||||
|
||||
#ifndef G3D_Sphere_h
|
||||
#define G3D_Sphere_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Vector3.h"
|
||||
#include "G3D/Array.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Sphere.
|
||||
*/
|
||||
class Sphere {
|
||||
private:
|
||||
|
||||
static int32 dummy;
|
||||
|
||||
public:
|
||||
Point3 center;
|
||||
float radius;
|
||||
|
||||
Sphere() : center(Point3::zero()), radius(0) {
|
||||
}
|
||||
|
||||
explicit Sphere(float radius) : radius(radius) {}
|
||||
|
||||
Sphere(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** Format is one of:
|
||||
- Sphere(point, radius)
|
||||
- Sphere(radius)
|
||||
*/
|
||||
explicit Sphere(const class Any& a);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
Sphere
|
||||
(const Point3& center,
|
||||
float radius) : center(center), radius(radius) {
|
||||
}
|
||||
|
||||
virtual ~Sphere() {}
|
||||
|
||||
/** Returns the infinite sphere. */
|
||||
static const Sphere& inf();
|
||||
|
||||
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 Point3& point) const;
|
||||
|
||||
bool contains(const Sphere& other) 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 = 0xFFFFFFFF) 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 = 0xFFFFFFFF) const;
|
||||
|
||||
virtual std::string toString() const;
|
||||
|
||||
float volume() const;
|
||||
|
||||
float area() const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the surface.
|
||||
*/
|
||||
Point3 randomSurfacePoint() const;
|
||||
|
||||
/**
|
||||
Uniformly distributed on the interior (includes surface)
|
||||
*/
|
||||
Point3 randomInteriorPoint() const;
|
||||
|
||||
void getBounds(class AABox& out) const;
|
||||
|
||||
bool intersects(const Sphere& other) const;
|
||||
|
||||
/** Translates the sphere */
|
||||
Sphere operator+(const Vector3& v) const {
|
||||
return Sphere(center + v, radius);
|
||||
}
|
||||
|
||||
/** Translates the sphere */
|
||||
Sphere operator-(const Vector3& v) const {
|
||||
return Sphere(center - v, radius);
|
||||
}
|
||||
|
||||
/** Sets this to the smallest sphere that encapsulates both */
|
||||
void merge(const Sphere& s);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template <> struct HashTrait<G3D::Sphere> {
|
||||
static size_t hashCode(const G3D::Sphere& key) {
|
||||
return static_cast<size_t>(key.center.hashCode() + (key.radius * 13));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
436
dep/g3dlite/include/G3D/Spline.h
Normal file
436
dep/g3dlite/include/G3D/Spline.h
Normal file
@@ -0,0 +1,436 @@
|
||||
/**
|
||||
\file G3D/Spline.h
|
||||
|
||||
\author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
|
||||
#ifndef G3D_Spline_h
|
||||
#define G3D_Spline_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Matrix4.h"
|
||||
#include "G3D/Vector4.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/SplineExtrapolationMode.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** Common implementation code for all G3D::Spline template parameters */
|
||||
class SplineBase {
|
||||
public:
|
||||
|
||||
/** Times at which control points occur. Must have the same
|
||||
number of elements as Spline::control. */
|
||||
Array<float> time;
|
||||
|
||||
/** If CYCLIC, then the control points will be assumed to wrap around.
|
||||
If LINEAR, then the tangents at the ends of the spline
|
||||
point to the final control points. If CONSTANT, the end control
|
||||
points will be treated as multiple contol points (so the value remains constant at the ends)
|
||||
*/
|
||||
SplineExtrapolationMode extrapolationMode;
|
||||
|
||||
/** For a cyclic spline, this is the time elapsed between the last
|
||||
control point and the first. If less than or equal to zero this is
|
||||
assumed to be:
|
||||
|
||||
(time[0] - time[1] + .
|
||||
time[time.size() - 1] - time[time.size() - 2]) / 2.
|
||||
*/
|
||||
float finalInterval;
|
||||
|
||||
SplineInterpolationMode interpolationMode;
|
||||
|
||||
SplineBase() :
|
||||
extrapolationMode(SplineExtrapolationMode::CYCLIC),
|
||||
finalInterval(-1),
|
||||
interpolationMode(SplineInterpolationMode::CUBIC) {}
|
||||
|
||||
virtual ~SplineBase() {}
|
||||
|
||||
/** See specification for Spline::finalInterval; this handles the
|
||||
non-positive case. Returns 0 if not cyclic. */
|
||||
float getFinalInterval() const;
|
||||
|
||||
/** Returns the amount of time covered by this spline in one
|
||||
period. For a cyclic spline, this contains the final
|
||||
interval.*/
|
||||
float duration() const;
|
||||
|
||||
/** Computes the derivative spline basis from the control point version. */
|
||||
static Matrix4 computeBasis();
|
||||
|
||||
protected:
|
||||
|
||||
/** Assumes that t0 <= s < tn. called by computeIndex. */
|
||||
void computeIndexInBounds(float s, int& i, float& u) const;
|
||||
|
||||
public:
|
||||
|
||||
/**
|
||||
Given a time @a s, finds @a i and 0 <= @a u < 1 such that
|
||||
@a s = time[@a i] * @a u + time[@a i + 1] * (1 - @a u). Note that
|
||||
@a i may be outside the bounds of the time and control arrays;
|
||||
use getControl to handle wraparound and extrapolation issues.
|
||||
|
||||
This function takes expected O(1) time for control points with
|
||||
uniform time sampled control points or for uniformly
|
||||
distributed random time samples, but may take O( log time.size() ) time
|
||||
in the worst case.
|
||||
|
||||
Called from evaluate().
|
||||
*/
|
||||
void computeIndex(float s, int& i, float& u) const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
Smooth parameteric curve implemented using a piecewise 3rd-order
|
||||
Catmull-Rom spline curve. The spline is considered infinite and may
|
||||
either continue linearly from the specified control points or cycle
|
||||
through them. Control points are spaced uniformly in time at unit
|
||||
intervals by default, but irregular spacing may be explicitly
|
||||
specified.
|
||||
|
||||
The dimension of the spline can be set by varying the Control
|
||||
template parameter. For a 1D function, use Spline<float>. For a
|
||||
curve in the plane, Spline<Vector2>. Note that <i>any</i> template
|
||||
parameter that supports operator+(Control) and operator*(float) can
|
||||
be used; you can make splines out of G3D::Vector4, G3D::Matrix3, or
|
||||
your own classes.
|
||||
|
||||
To provide shortest-path interpolation, subclass G3D::Spline and
|
||||
override ensureShortestPath(). To provide normalization of
|
||||
interpolated points (e.g., projecting Quats onto the unit
|
||||
hypersphere) override correct().
|
||||
|
||||
See Real Time Rendering, 2nd edition, ch 12 for a general discussion
|
||||
of splines and their properties.
|
||||
|
||||
\sa G3D::UprightSpline
|
||||
*/
|
||||
template<typename Control>
|
||||
class Spline : public SplineBase {
|
||||
protected:
|
||||
/** The additive identity control point. */
|
||||
Control zero;
|
||||
|
||||
public:
|
||||
|
||||
/** Control points. Must have the same number of elements as
|
||||
Spline::time.*/
|
||||
Array<Control> control;
|
||||
|
||||
Spline() {
|
||||
static Control x;
|
||||
// Hide the fact from C++ that we are using an
|
||||
// uninitialized variable here by pointer arithmetic.
|
||||
// This is ok because any type that is a legal control
|
||||
// point also supports multiplication by float.
|
||||
zero = *(&x) * 0.0f;
|
||||
}
|
||||
|
||||
/** Appends a control point at a specific time that must be
|
||||
greater than that of the previous point. */
|
||||
void append(float t, const Control& c) {
|
||||
debugAssertM((time.size() == 0) || (t > time.last()),
|
||||
"Control points must have monotonically increasing times.");
|
||||
time.append(t);
|
||||
control.append(c);
|
||||
debugAssert(control.size() == time.size());
|
||||
}
|
||||
|
||||
|
||||
/** Appends control point spaced in time based on the previous
|
||||
control point, or spaced at unit intervals if this is the
|
||||
first control point. */
|
||||
void append(const Control& c) {
|
||||
switch (time.size()) {
|
||||
case 0:
|
||||
append(0, c);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
append(time[0] + 1, c);
|
||||
break;
|
||||
|
||||
default:
|
||||
append(2 * time[time.size() - 1] - time[time.size() - 2], c);
|
||||
}
|
||||
debugAssert(control.size() == time.size());
|
||||
}
|
||||
|
||||
/** Erases all control points and times, but retains the state of
|
||||
cyclic and finalInterval.
|
||||
*/
|
||||
void clear() {
|
||||
control.clear();
|
||||
time.clear();
|
||||
}
|
||||
|
||||
|
||||
/** Number of control points */
|
||||
int size() const {
|
||||
debugAssert(time.size() == control.size());
|
||||
return control.size();
|
||||
}
|
||||
|
||||
|
||||
/** Returns the requested control point and time sample based on
|
||||
array index. If the array index is out of bounds, wraps (for
|
||||
a cyclic spline) or linearly extrapolates (for a non-cyclic
|
||||
spline), assuming time intervals follow the first or last
|
||||
sample recorded.
|
||||
|
||||
Calls correct() on the control point if it was extrapolated.
|
||||
|
||||
Returns 0 if there are no control points.
|
||||
|
||||
@sa Spline::control and Spline::time for the underlying
|
||||
control point array; Spline::computeIndex to find the index
|
||||
given a time.
|
||||
*/
|
||||
void getControl(int i, float& t, Control& c) const {
|
||||
int N = control.size();
|
||||
if (N == 0) {
|
||||
c = zero;
|
||||
t = 0;
|
||||
} else if (extrapolationMode == SplineExtrapolationMode::CYCLIC) {
|
||||
c = control[iWrap(i, N)];
|
||||
|
||||
if (i < 0) {
|
||||
// Wrapped around bottom
|
||||
|
||||
// Number of times we wrapped around the cyclic array
|
||||
int wraps = (N + 1 - i) / N;
|
||||
int j = (i + wraps * N) % N;
|
||||
t = time[j] - wraps * duration();
|
||||
|
||||
} else if (i < N) {
|
||||
|
||||
t = time[i];
|
||||
|
||||
} else {
|
||||
// Wrapped around top
|
||||
|
||||
// Number of times we wrapped around the cyclic array
|
||||
int wraps = i / N;
|
||||
int j = i % N;
|
||||
t = time[j] + wraps * duration();
|
||||
}
|
||||
|
||||
} else if (i < 0) {
|
||||
// Are there enough points to extrapolate?
|
||||
if (N >= 2) {
|
||||
// Step away from control point 0
|
||||
float dt = time[1] - time[0];
|
||||
|
||||
if (extrapolationMode == SplineExtrapolationMode::LINEAR) {
|
||||
// Extrapolate (note; i is negative)
|
||||
c = control[1] * float(i) + control[0] * float(1 - i);
|
||||
correct(c);
|
||||
} else if (extrapolationMode == SplineExtrapolationMode::CLAMP){
|
||||
// Return the first, clamping
|
||||
c = control[0];
|
||||
} else {
|
||||
alwaysAssertM(false, "Invalid extrapolation mode");
|
||||
}
|
||||
t = dt * i + time[0];
|
||||
|
||||
} else {
|
||||
// Just clamp
|
||||
c = control[0];
|
||||
|
||||
// Only 1 time; assume 1s intervals
|
||||
t = time[0] + i;
|
||||
}
|
||||
|
||||
} else if (i >= N) {
|
||||
if (N >= 2) {
|
||||
float dt = time[N - 1] - time[N - 2];
|
||||
|
||||
if (extrapolationMode == SplineExtrapolationMode::LINEAR) {
|
||||
// Extrapolate (note; i is negative)
|
||||
c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1);
|
||||
correct(c);
|
||||
} else if (extrapolationMode == SplineExtrapolationMode::CLAMP){
|
||||
// Return the last, clamping
|
||||
c = control.last();
|
||||
} else {
|
||||
alwaysAssertM(false, "Invalid extrapolation mode");
|
||||
}
|
||||
// Extrapolate
|
||||
t = time[N - 1] + dt * (i - N + 1);
|
||||
|
||||
} else {
|
||||
// Return the last, clamping
|
||||
c = control.last();
|
||||
// Only 1 time; assume 1s intervals
|
||||
t = time[0] + i;
|
||||
}
|
||||
} else {
|
||||
// In bounds
|
||||
c = control[i];
|
||||
t = time[i];
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
/** Returns a series of N control points and times, fixing
|
||||
boundary issues. The indices may be assumed to be treated
|
||||
cyclically. */
|
||||
void getControls(int i, float* T, Control* A, int N) const {
|
||||
for (int j = 0; j < N; ++j) {
|
||||
getControl(i + j, T[j], A[j]);
|
||||
}
|
||||
ensureShortestPath(A, N);
|
||||
}
|
||||
|
||||
/**
|
||||
Mutates the array of N control points that begins at \a A. It is useful to override this
|
||||
method by one that wraps the values if they are angles or quaternions
|
||||
for which "shortest path" interpolation is significant.
|
||||
*/
|
||||
virtual void ensureShortestPath(Control* A, int N) const { (void)A; (void) N;}
|
||||
|
||||
/** Normalize or otherwise adjust this interpolated Control. */
|
||||
virtual void correct(Control& A) const { (void)A; }
|
||||
|
||||
/** Does not invoke verifyDone() on the propertyTable because subclasses may have more properties */
|
||||
virtual void init(AnyTableReader& propertyTable) {
|
||||
propertyTable.getIfPresent("extrapolationMode", extrapolationMode);
|
||||
propertyTable.getIfPresent("interpolationMode", interpolationMode);
|
||||
propertyTable.getIfPresent("finalInterval", finalInterval);
|
||||
|
||||
const bool hasTime = propertyTable.getIfPresent("time", time);
|
||||
|
||||
if (propertyTable.getIfPresent("control", control)) {
|
||||
if (! hasTime) {
|
||||
// Assign unit times
|
||||
time.resize(control.size());
|
||||
for (int i = 0; i < time.size(); ++i) {
|
||||
time[i] = float(i);
|
||||
}
|
||||
} // if has time
|
||||
} // if has control
|
||||
} // init
|
||||
|
||||
public:
|
||||
|
||||
/** Accepts a table of properties, or any valid PhysicsFrame specification for a single control*/
|
||||
explicit Spline(const Any& any) {
|
||||
AnyTableReader propertyTable(any);
|
||||
init(propertyTable);
|
||||
propertyTable.verifyDone();
|
||||
}
|
||||
|
||||
/** Note that invoking classes can call setName on the returned value instead of passing a name in. */
|
||||
virtual Any toAny(const std::string& myName) const {
|
||||
Any a(Any::TABLE, myName);
|
||||
|
||||
a["extrapolationMode"] = extrapolationMode;
|
||||
a["interpolationMode"] = interpolationMode;
|
||||
a["control"] = Any(control);
|
||||
a["time"] = Any(time);
|
||||
a["finalInterval"] = finalInterval;
|
||||
|
||||
return a;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Return the position at time s. The spline is defined outside
|
||||
of the time samples by extrapolation or cycling.
|
||||
*/
|
||||
Control evaluate(float s) const {
|
||||
debugAssertM(control.size() == time.size(), "Corrupt spline: wrong number of control points.");
|
||||
|
||||
/*
|
||||
@cite http://www.gamedev.net/reference/articles/article1497.asp
|
||||
Derivation of basis matrix follows.
|
||||
|
||||
Given control points with positions p[i] at times t[i], 0 <= i <= 3, find the position
|
||||
at time t[1] <= s <= t[2].
|
||||
|
||||
Let u = s - t[0]
|
||||
Let U = [u^0 u^1 u^2 u^3] = [1 u u^2 u^3]
|
||||
Let dt0 = t[0] - t[-1]
|
||||
Let dt1 = t[1] - t[0]
|
||||
Let dt2 = t[2] - t[1]
|
||||
*/
|
||||
|
||||
// Index of the first control point (i.e., the u = 0 point)
|
||||
int i = 0;
|
||||
// Fractional part of the time
|
||||
float u = 0;
|
||||
|
||||
computeIndex(s, i, u);
|
||||
|
||||
Control p[4];
|
||||
float t[4];
|
||||
getControls(i - 1, t, p, 4);
|
||||
|
||||
const Control& p0 = p[0];
|
||||
const Control& p1 = p[1];
|
||||
const Control& p2 = p[2];
|
||||
const Control& p3 = p[3];
|
||||
|
||||
// Compute the weighted sum of the neighboring control points.
|
||||
Control sum;
|
||||
|
||||
if (interpolationMode == SplineInterpolationMode::LINEAR) {
|
||||
const float a = (s - t[1]) / (t[2] - t[1]);
|
||||
sum = p1 * (1.0f - a) + p2 * a;
|
||||
correct(sum);
|
||||
return sum;
|
||||
}
|
||||
|
||||
float dt0 = t[1] - t[0];
|
||||
float dt1 = t[2] - t[1];
|
||||
float dt2 = t[3] - t[2];
|
||||
|
||||
static const Matrix4 basis = computeBasis();
|
||||
|
||||
// Powers of u
|
||||
Vector4 uvec((float)(u*u*u), (float)(u*u), (float)u, 1.0f);
|
||||
|
||||
// Compute the weights on each of the control points.
|
||||
const Vector4& weights = uvec * basis;
|
||||
|
||||
|
||||
// The factor of 1/2 from averaging two time intervals is
|
||||
// already factored into the basis
|
||||
|
||||
// tan1 = (dp0 / dt0 + dp1 / dt1) * ((dt0 + dt1) * 0.5);
|
||||
// The last term normalizes for unequal time intervals
|
||||
float x = (dt0 + dt1) * 0.5f;
|
||||
float n0 = x / dt0;
|
||||
float n1 = x / dt1;
|
||||
float n2 = x / dt2;
|
||||
|
||||
const Control& dp0 = p1 + (p0*-1.0f);
|
||||
const Control& dp1 = p2 + (p1*-1.0f);
|
||||
const Control& dp2 = p3 + (p2*-1.0f);
|
||||
|
||||
const Control& dp1n1 = dp1 * n1;
|
||||
const Control& tan1 = dp0 * n0 + dp1n1;
|
||||
const Control& tan2 = dp1n1 + dp2 * n2;
|
||||
|
||||
sum =
|
||||
tan1 * weights[0] +
|
||||
p1 * weights[1] +
|
||||
p2 * weights[2] +
|
||||
tan2 * weights[3];
|
||||
|
||||
|
||||
correct(sum);
|
||||
return sum;
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
94
dep/g3dlite/include/G3D/SplineExtrapolationMode.h
Normal file
94
dep/g3dlite/include/G3D/SplineExtrapolationMode.h
Normal file
@@ -0,0 +1,94 @@
|
||||
/**
|
||||
\file G3D/SplineExtrapolationMode.h
|
||||
|
||||
\maintainer Michael Mara, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2013-01-24
|
||||
\edited 2013-01-24
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_SplineExtrapolationMode_h
|
||||
#define G3D_SplineExtrapolationMode_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/enumclass.h"
|
||||
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Describes the behavior of G3D::Spline, etc. when accessing a time outside of the control point range.
|
||||
|
||||
Refer to these as scoped enums, e.g., <code>SplineExtrapolationMode m = SplineExtrapolationMode::CLAMP;</code>.
|
||||
|
||||
Uses the "Intelligent Enum" design pattern
|
||||
http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/
|
||||
*/
|
||||
class SplineExtrapolationMode {
|
||||
public:
|
||||
/** Don't use this enum; use SplineExtrapolationMode instances instead. */
|
||||
enum Value {
|
||||
CYCLIC,
|
||||
LINEAR,
|
||||
CLAMP
|
||||
};
|
||||
Value value;
|
||||
private:
|
||||
|
||||
static const char* toString(int i, Value& v) {
|
||||
static const char* str[] = {"CYCLIC", "LINEAR", "CLAMP", NULL};
|
||||
static const Value val[] = {CYCLIC, LINEAR, CLAMP};
|
||||
const char* s = str[i];
|
||||
if (s) {
|
||||
v = val[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
G3D_DECLARE_ENUM_CLASS_METHODS(SplineExtrapolationMode);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
Describes the behavior of G3D::Spline
|
||||
*/
|
||||
class SplineInterpolationMode {
|
||||
public:
|
||||
/** Don't use this enum; use SplineExtrapolationMode instances instead. */
|
||||
enum Value {
|
||||
LINEAR,
|
||||
CUBIC
|
||||
};
|
||||
Value value;
|
||||
private:
|
||||
|
||||
static const char* toString(int i, Value& v) {
|
||||
static const char* str[] = {"LINEAR", "CUBIC", NULL};
|
||||
static const Value val[] = {LINEAR, CUBIC};
|
||||
const char* s = str[i];
|
||||
if (s) {
|
||||
v = val[i];
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
G3D_DECLARE_ENUM_CLASS_METHODS(SplineInterpolationMode);
|
||||
|
||||
};
|
||||
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::SplineExtrapolationMode);
|
||||
G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::SplineInterpolationMode);
|
||||
|
||||
#endif
|
||||
159
dep/g3dlite/include/G3D/Stopwatch.h
Normal file
159
dep/g3dlite/include/G3D/Stopwatch.h
Normal file
@@ -0,0 +1,159 @@
|
||||
/**
|
||||
@file Stopwatch.h
|
||||
|
||||
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
@created 2005-10-05
|
||||
@edited 2009-05-10
|
||||
|
||||
Copyright 2000-2009, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Stopwatch_h
|
||||
#define G3D_Stopwatch_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Queue.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief Accurately measure durations and framerates.
|
||||
|
||||
Example 1: For profiling code in the context of a rendering loop:
|
||||
<pre>
|
||||
sw.tick();
|
||||
...timed code...
|
||||
sw.tock();
|
||||
|
||||
screenPrintf("%f\n", sw.smoothFPS());
|
||||
</pre>
|
||||
|
||||
|
||||
Example 2: For profiling pieces of a sequence:
|
||||
<pre>
|
||||
Stopwatch sw;
|
||||
slowOperation();
|
||||
sw.after("slowOperation");
|
||||
kdTree.balance();
|
||||
sw.after("Balance tree");
|
||||
</pre>
|
||||
*/
|
||||
class Stopwatch {
|
||||
private:
|
||||
|
||||
std::string myName;
|
||||
|
||||
bool m_enabled;
|
||||
|
||||
double startTime;
|
||||
std::string prevMark;
|
||||
double prevTime;
|
||||
|
||||
/** True between tick and tock */
|
||||
bool inBetween;
|
||||
|
||||
/** The initial cycle count. */
|
||||
uint64 cycleStart;
|
||||
|
||||
/** The time at which tick was called. */
|
||||
RealTime timeStart;
|
||||
|
||||
/** The time at which the previous tock was called, -1 if never. */
|
||||
RealTime lastTockTime;
|
||||
|
||||
RealTime lastDuration;
|
||||
int64 lastCycleCount;
|
||||
|
||||
/** Frames per second. */
|
||||
double m_fps;
|
||||
|
||||
/** Weighted fps */
|
||||
double emwaFPS;
|
||||
double m_smoothFPS;
|
||||
|
||||
/** Weighted duration */
|
||||
RealTime emwaDuration;
|
||||
|
||||
/** The overhead for calling into the class. */
|
||||
int64 cycleOverhead;
|
||||
|
||||
/** Called from the constructor. */
|
||||
void computeOverhead();
|
||||
|
||||
public:
|
||||
|
||||
Stopwatch(const std::string& name = "Stopwatch");
|
||||
|
||||
void setEnabled(bool e) {
|
||||
m_enabled = e;
|
||||
}
|
||||
|
||||
/** A stopwatch only prints output when enabled */
|
||||
bool enabled() const {
|
||||
return m_enabled;
|
||||
}
|
||||
|
||||
/** Returns the number of times that tick was called per wall-clock second;
|
||||
e.g. frames-per-second. */
|
||||
double FPS() const {
|
||||
return m_fps;
|
||||
}
|
||||
|
||||
/** Amount of time between the most recent tick and tock calls. 0 if tick has
|
||||
never been called. */
|
||||
RealTime elapsedTime() const {
|
||||
return lastDuration;
|
||||
}
|
||||
|
||||
/** Time-smoothed value that is stable to the nearest 1%.
|
||||
This is useful if you are displaying elapsed time in real-time
|
||||
and want a stable number.*/
|
||||
RealTime smoothElapsedTime() const {
|
||||
return emwaDuration;
|
||||
}
|
||||
|
||||
/** Time-smoothed value of fps that is stable to the nearest integer for fps > 10 and
|
||||
to the first decimal place for fps <= 10.
|
||||
This is useful if you
|
||||
are displaying the frame rate in real-time and want a stable (readable) number.*/
|
||||
double smoothFPS() const {
|
||||
return m_smoothFPS;
|
||||
}
|
||||
|
||||
/** The elapsed cycle time between tick and tock. An attempt is made to factor out all
|
||||
tick/tock overhead, so that back-to-back calls should return zero.
|
||||
Unreliable on non-x86 platforms.*/
|
||||
uint64 elapsedCycles() const {
|
||||
return lastCycleCount;
|
||||
}
|
||||
|
||||
/** Call at the beginning of the period that you want timed. */
|
||||
void tick();
|
||||
|
||||
/** Call at the end of the period that you want timed. */
|
||||
void tock();
|
||||
|
||||
|
||||
/** Reset the start time used by after() and the emwa value.*/
|
||||
void reset();
|
||||
|
||||
/** Call after an operation has completed, with the name of the operation, to
|
||||
print a debug message listing the time since the previous after() call.
|
||||
|
||||
Does nothing if the stopwatch is disabled.
|
||||
*/
|
||||
void after(const std::string& s = "");
|
||||
|
||||
};
|
||||
|
||||
/** Because it is hard to remember the proper capitalization. */
|
||||
typedef Stopwatch StopWatch;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
551
dep/g3dlite/include/G3D/System.h
Normal file
551
dep/g3dlite/include/G3D/System.h
Normal file
@@ -0,0 +1,551 @@
|
||||
/**
|
||||
\file System.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\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 2012-10-02
|
||||
*/
|
||||
|
||||
#ifndef G3D_System_h
|
||||
#define G3D_System_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/G3DGameUnits.h"
|
||||
#include "G3D/BinaryFormat.h"
|
||||
#include "G3D/FileNotFound.h"
|
||||
#include <string>
|
||||
|
||||
#ifdef G3D_OSX
|
||||
#define Zone OSX_Zone
|
||||
# include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/** G3D, SDL, and IJG libraries require license documentation
|
||||
to be distributed with your program. This generates the
|
||||
string that must appear in your documentation.
|
||||
<B>Your program can be commercial, closed-source</B> under
|
||||
any license you want.
|
||||
@deprecated Use System::license
|
||||
*/
|
||||
std::string license();
|
||||
|
||||
/**
|
||||
@brief The order in which the bytes of an integer are stored on a
|
||||
machine.
|
||||
|
||||
Intel/AMD chips tend to be G3D_LITTLE_ENDIAN, Mac PPC's and Suns are
|
||||
G3D_BIG_ENDIAN. However, this is primarily used to specify the byte
|
||||
order of file formats, which are fixed.
|
||||
*/
|
||||
enum G3DEndian {
|
||||
G3D_BIG_ENDIAN,
|
||||
G3D_LITTLE_ENDIAN
|
||||
};
|
||||
|
||||
/**
|
||||
@brief OS and processor abstraction.
|
||||
|
||||
The first time any method is called the processor will be analyzed.
|
||||
Future calls are then fast.
|
||||
|
||||
Timing function overview:
|
||||
System::getCycleCount
|
||||
- actual cycle count
|
||||
|
||||
System::getTick
|
||||
- High-resolution time in seconds since program started
|
||||
|
||||
System::getLocalTime
|
||||
- High-resolution time in seconds since Jan 1, 1970
|
||||
(because it is stored in a double, this may be less
|
||||
accurate than getTick)
|
||||
*/
|
||||
class System {
|
||||
public:
|
||||
/**
|
||||
@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);
|
||||
|
||||
private:
|
||||
|
||||
bool m_initialized;
|
||||
int m_cpuSpeed;
|
||||
bool m_hasCPUID;
|
||||
bool m_hasRDTSC;
|
||||
bool m_hasMMX;
|
||||
bool m_hasSSE;
|
||||
bool m_hasSSE2;
|
||||
bool m_hasSSE3;
|
||||
bool m_has3DNOW;
|
||||
bool m_has3DNOW2;
|
||||
bool m_hasAMDMMX;
|
||||
std::string m_cpuVendor;
|
||||
int m_numCores;
|
||||
|
||||
/** this holds the data directory set by the application (currently
|
||||
GApp) for use by findDataFile */
|
||||
std::string m_appDataDir;
|
||||
|
||||
G3DEndian m_machineEndian;
|
||||
std::string m_cpuArch;
|
||||
std::string m_operatingSystem;
|
||||
|
||||
# ifdef G3D_WINDOWS
|
||||
/** Used by getTick() for timing */
|
||||
LARGE_INTEGER m_start;
|
||||
LARGE_INTEGER m_counterFrequency;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
#endif
|
||||
|
||||
std::string m_version;
|
||||
OutOfMemoryCallback m_outOfMemoryCallback;
|
||||
|
||||
#ifdef G3D_OSX
|
||||
/** In Cycles/Second */
|
||||
SInt32 m_OSXCPUSpeed;
|
||||
double m_secondsPerNS;
|
||||
#endif
|
||||
|
||||
/** The Real-World time of System::getTick() time 0. Set by initTime */
|
||||
RealTime m_realWorldGetTickTime0;
|
||||
|
||||
uint32 m_highestCPUIDFunction;
|
||||
|
||||
/** @brief Used for the singleton instance only. */
|
||||
System();
|
||||
|
||||
/** @brief The singleton instance.
|
||||
|
||||
Used instead of a global variable to ensure that the order of
|
||||
intialization is correct, which is critical because other
|
||||
globals may allocate memory using System::malloc.
|
||||
*/
|
||||
static System& instance();
|
||||
|
||||
enum CPUIDFunction {
|
||||
CPUID_VENDOR_ID = 0x00000000,
|
||||
CPUID_PROCESSOR_FEATURES = 0x00000001,
|
||||
CPUID_NUM_CORES = 0x00000004,
|
||||
CPUID_GET_HIGHEST_FUNCTION = 0x80000000,
|
||||
CPUID_EXTENDED_FEATURES = 0x80000001};
|
||||
|
||||
/** Helper macro to call cpuid functions and return all values
|
||||
|
||||
See http://software.intel.com/en-us/articles/intel-64-architecture-processor-topology-enumeration/
|
||||
or http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/25481.pdf
|
||||
|
||||
for description of the arguments.
|
||||
*/
|
||||
static void cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg);
|
||||
|
||||
|
||||
/** Called from init() */
|
||||
void getStandardProcessorExtensions();
|
||||
|
||||
/** Called from init() */
|
||||
void initTime();
|
||||
|
||||
void init();
|
||||
|
||||
public:
|
||||
|
||||
/** atexit handling code invoked from G3DCleanupHook. */
|
||||
static void cleanup();
|
||||
|
||||
/** Returns the speed of processor 0 in MHz.
|
||||
Always returns 0 on linux.*/
|
||||
inline static int cpuSpeedMHz() {
|
||||
return instance().m_cpuSpeed;
|
||||
}
|
||||
|
||||
/** Returns the number of logical processor cores (i.e., the
|
||||
number of execution units for threads) */
|
||||
inline static int numCores() {
|
||||
return instance().m_numCores;
|
||||
}
|
||||
|
||||
inline static bool hasCPUID() {
|
||||
return instance().m_hasCPUID;
|
||||
}
|
||||
|
||||
inline static bool hasRDTSC() {
|
||||
return instance().m_hasRDTSC;
|
||||
}
|
||||
|
||||
inline static bool hasSSE() {
|
||||
return instance().m_hasSSE;
|
||||
}
|
||||
|
||||
inline static bool hasSSE2() {
|
||||
return instance().m_hasSSE2;
|
||||
}
|
||||
|
||||
inline static bool hasSSE3() {
|
||||
return instance().m_hasSSE3;
|
||||
}
|
||||
|
||||
inline static bool hasMMX() {
|
||||
return instance().m_hasMMX;
|
||||
}
|
||||
|
||||
inline static bool has3DNow() {
|
||||
return instance().m_has3DNOW;
|
||||
}
|
||||
|
||||
inline static const std::string& cpuVendor() {
|
||||
return instance().m_cpuVendor;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the endianness of this machine.
|
||||
*/
|
||||
inline static G3DEndian machineEndian() {
|
||||
return instance().m_machineEndian;
|
||||
}
|
||||
|
||||
/** e.g., "Windows", "GNU/Linux" */
|
||||
inline static const std::string& operatingSystem() {
|
||||
return instance().m_operatingSystem;
|
||||
}
|
||||
|
||||
/** e.g., 80686 */
|
||||
inline static const std::string& cpuArchitecture() {
|
||||
return instance().m_cpuArch;
|
||||
}
|
||||
|
||||
/**
|
||||
Returns the current date as a string in the form YYYY-MM-DD
|
||||
*/
|
||||
static std::string currentDateString();
|
||||
|
||||
/** Returns the current 24-hour local time as a string in the form HH:MM:SS */
|
||||
static std::string currentTimeString();
|
||||
|
||||
/**
|
||||
Uses pooled storage to optimize small allocations (1 byte to 5
|
||||
kilobytes). Can be 10x to 100x faster than calling \c malloc or
|
||||
\c 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);
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
/**
|
||||
Guarantees that the start of the array is aligned to the
|
||||
specified number of bytes.
|
||||
*/
|
||||
static void* alignedMalloc(size_t bytes, size_t alignment);
|
||||
|
||||
/**
|
||||
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);
|
||||
|
||||
/**
|
||||
Returns the fully qualified filename for the currently running executable.
|
||||
|
||||
This is more reliable than arg[0], which may be intentionally set
|
||||
to an incorrect value by a calling program, relative to a now
|
||||
non-current directory, or obfuscated by sym-links.
|
||||
|
||||
@cite Linux version written by Nicolai Haehnle <prefect_@gmx.net>, http://www.flipcode.com/cgi-bin/msg.cgi?showThread=COTD-getexename&forum=cotd&id=-1
|
||||
*/
|
||||
static std::string currentProgramFilename();
|
||||
|
||||
/** Name of this program. Note that you can mutate this string to
|
||||
set your app name explicitly.*/
|
||||
static std::string& appName();
|
||||
|
||||
/** G3D Version string */
|
||||
inline static const std::string& version() {
|
||||
return instance().m_version;
|
||||
}
|
||||
|
||||
/**
|
||||
@brief The optimization status of the G3D library (not the program compiled against it)
|
||||
|
||||
Either "Debug" or "Release", depending on whether _DEBUG was
|
||||
defined at compile-time for the library.
|
||||
*/
|
||||
static const std::string& build();
|
||||
|
||||
/**
|
||||
Causes the current thread to yield for the specified duration
|
||||
and consume almost no CPU.
|
||||
The sleep will be extremely precise; it uses System::time()
|
||||
to calibrate the exact yeild time.
|
||||
*/
|
||||
static void sleep(RealTime t);
|
||||
|
||||
/**
|
||||
Clears the console.
|
||||
Console programs only.
|
||||
*/
|
||||
static void consoleClearScreen();
|
||||
|
||||
/**
|
||||
Returns true if a key is waiting.
|
||||
Console programs only.
|
||||
*/
|
||||
static bool consoleKeyPressed();
|
||||
|
||||
/**
|
||||
Blocks until a key is read (use consoleKeyPressed to determine if
|
||||
a key is waiting to be read) then returns the character code for
|
||||
that key.
|
||||
*/
|
||||
static int consoleReadKey();
|
||||
|
||||
/**
|
||||
The actual time (measured in seconds since
|
||||
Jan 1 1970 midnight).
|
||||
|
||||
Adjusted for local timezone and daylight savings
|
||||
time. This is as accurate and fast as getCycleCount().
|
||||
*/
|
||||
static RealTime time();
|
||||
|
||||
/**
|
||||
To count the number of cycles a given operation takes:
|
||||
|
||||
\htmlonly
|
||||
<PRE>
|
||||
unsigned long count;
|
||||
System::beginCycleCount(count);
|
||||
...
|
||||
System::endCycleCount(count);
|
||||
// count now contains the cycle count for the intervening operation.
|
||||
</PRE>
|
||||
\endhtmlonly
|
||||
*/
|
||||
static void beginCycleCount(uint64& cycleCount);
|
||||
static void endCycleCount(uint64& cycleCount);
|
||||
|
||||
static uint64 getCycleCount();
|
||||
|
||||
inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) {
|
||||
instance().m_outOfMemoryCallback = c;
|
||||
}
|
||||
|
||||
/**
|
||||
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.
|
||||
*/
|
||||
inline static OutOfMemoryCallback outOfMemoryCallback() {
|
||||
return instance().m_outOfMemoryCallback;
|
||||
}
|
||||
|
||||
/** Set an environment variable for the current process */
|
||||
static void setEnv(const std::string& name, const std::string& value);
|
||||
|
||||
/** Get an environment variable for the current process. Returns NULL if the variable doesn't exist. */
|
||||
static const char* getEnv(const std::string& name);
|
||||
|
||||
/**
|
||||
Prints a human-readable description of this machine
|
||||
to the text output stream. Either argument may be NULL.
|
||||
*/
|
||||
static void describeSystem
|
||||
(class TextOutput& t);
|
||||
|
||||
static void describeSystem
|
||||
(std::string& s);
|
||||
|
||||
/**
|
||||
Tries to locate the resource by looking in related directories.
|
||||
If found, returns the full path to the resource, otherwise
|
||||
returns the empty string.
|
||||
|
||||
Looks in:
|
||||
|
||||
- Literal interpretation of full (i.e., if it contains a fully-qualified name)
|
||||
- Last directory in which a file was found
|
||||
- Current directory
|
||||
- System::appDataDir (which is usually GApp::Settings.dataDir, which defaults to the directory containing the program binary)
|
||||
- $G3D9DATA directory
|
||||
- System::appDataDir() + "data/" (note that this may be a zipfile named "data" with no extension)
|
||||
- System::appDataDir() + "data.zip/"
|
||||
- ../data-files/ (windows)
|
||||
- ../../data-files/ (windows)
|
||||
- ../../../data-files/ (windows)
|
||||
|
||||
Plus the following subdirectories of those:
|
||||
|
||||
- cubemap
|
||||
- gui
|
||||
- font
|
||||
- icon
|
||||
- models
|
||||
- image
|
||||
- sky
|
||||
- md2
|
||||
- md3
|
||||
- ifs
|
||||
- 3ds
|
||||
|
||||
\param exceptionIfNotFound If true and the file is not found, throws G3D::FileNotFound.
|
||||
*/
|
||||
static std::string findDataFile(const std::string& full, bool exceptionIfNotFound = true, bool caseSensitive =
|
||||
#ifdef G3D_WINDOWS
|
||||
false
|
||||
#else
|
||||
true
|
||||
#endif
|
||||
);
|
||||
|
||||
/**
|
||||
Sets the path that the application is using as its data directory.
|
||||
Used by findDataDir as an initial search location. GApp sets this
|
||||
upon constrution.
|
||||
*/
|
||||
static void setAppDataDir(const std::string& path);
|
||||
|
||||
};
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
# ifdef _M_IX86
|
||||
// 32-bit
|
||||
inline uint64 System::getCycleCount() {
|
||||
uint32 timehi, timelo;
|
||||
|
||||
// Use the assembly instruction rdtsc, which gets the current
|
||||
// cycle count (since the process started) and puts it in edx:eax.
|
||||
__asm
|
||||
{
|
||||
rdtsc;
|
||||
mov timehi, edx;
|
||||
mov timelo, eax;
|
||||
}
|
||||
|
||||
return ((uint64)timehi << 32) + (uint64)timelo;
|
||||
}
|
||||
# else
|
||||
// 64-bit
|
||||
inline uint64 System::getCycleCount() {
|
||||
LARGE_INTEGER now;
|
||||
QueryPerformanceCounter(&now);
|
||||
return now.QuadPart;
|
||||
}
|
||||
|
||||
# endif
|
||||
|
||||
#elif defined(G3D_LINUX)
|
||||
|
||||
inline uint64 System::getCycleCount() {
|
||||
uint32 timehi, timelo;
|
||||
|
||||
__asm__ __volatile__ (
|
||||
"rdtsc "
|
||||
: "=a" (timelo),
|
||||
"=d" (timehi)
|
||||
: );
|
||||
|
||||
return ((uint64)timehi << 32) + (uint64)timelo;
|
||||
}
|
||||
|
||||
#elif defined(G3D_OSX)
|
||||
|
||||
inline uint64 System::getCycleCount() {
|
||||
//Note: To put off extra processing until the end, this does not
|
||||
//return the actual clock cycle count. It is a bus cycle count.
|
||||
//When endCycleCount() is called, it converts the two into a difference
|
||||
//of clock cycles
|
||||
|
||||
return (uint64) UnsignedWideToUInt64(UpTime());
|
||||
//return (uint64) mach_absolute_time();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
inline void System::beginCycleCount(uint64& cycleCount) {
|
||||
cycleCount = getCycleCount();
|
||||
}
|
||||
|
||||
|
||||
inline void System::endCycleCount(uint64& cycleCount) {
|
||||
#ifndef G3D_OSX
|
||||
cycleCount = getCycleCount() - cycleCount;
|
||||
#else
|
||||
AbsoluteTime end = UpTime();
|
||||
Nanoseconds diffNS =
|
||||
AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
|
||||
cycleCount =
|
||||
(uint64) ((double) (instance().m_OSXCPUSpeed) *
|
||||
(double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
} // namespace
|
||||
|
||||
|
||||
#ifdef G3D_OSX
|
||||
#undef Zone
|
||||
#endif
|
||||
|
||||
#endif
|
||||
1008
dep/g3dlite/include/G3D/Table.h
Normal file
1008
dep/g3dlite/include/G3D/Table.h
Normal file
File diff suppressed because it is too large
Load Diff
869
dep/g3dlite/include/G3D/TextInput.h
Normal file
869
dep/g3dlite/include/G3D/TextInput.h
Normal file
@@ -0,0 +1,869 @@
|
||||
/**
|
||||
\file G3D/TextInput.h
|
||||
|
||||
Simple text lexer/tokenizer.
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\cite Based on a lexer written by Aaron Orenstein.
|
||||
|
||||
\created 2002-11-27
|
||||
\edited 2013-03-25
|
||||
|
||||
Copyright 2000-2013, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TextInput_h
|
||||
#define G3D_TextInput_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/Set.h"
|
||||
#include "G3D/ParseError.h"
|
||||
#include <string>
|
||||
#include <queue>
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
For use with TextInput.
|
||||
*/
|
||||
class Token {
|
||||
public:
|
||||
|
||||
/**
|
||||
More detailed type information than Type.
|
||||
*/
|
||||
enum ExtendedType {
|
||||
DOUBLE_QUOTED_TYPE,
|
||||
SINGLE_QUOTED_TYPE,
|
||||
SYMBOL_TYPE,
|
||||
FLOATING_POINT_TYPE,
|
||||
INTEGER_TYPE,
|
||||
BOOLEAN_TYPE,
|
||||
LINE_COMMENT_TYPE,
|
||||
BLOCK_COMMENT_TYPE,
|
||||
NEWLINE_TYPE,
|
||||
END_TYPE
|
||||
};
|
||||
|
||||
/**
|
||||
Strings are enclosed in quotes, symbols are not.
|
||||
*/
|
||||
enum Type {
|
||||
STRING = DOUBLE_QUOTED_TYPE,
|
||||
SYMBOL = SYMBOL_TYPE,
|
||||
NUMBER = FLOATING_POINT_TYPE,
|
||||
BOOLEAN = BOOLEAN_TYPE,
|
||||
COMMENT = LINE_COMMENT_TYPE,
|
||||
NEWLINE = NEWLINE_TYPE,
|
||||
END = END_TYPE
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
friend class TextInput;
|
||||
|
||||
/**
|
||||
Holds the actual value, which might be any type. If a number, it will be
|
||||
parsed at runtime.
|
||||
*/
|
||||
std::string _string;
|
||||
|
||||
bool _bool;
|
||||
int _line;
|
||||
int _character;
|
||||
uint64 _bytePosition;
|
||||
Type _type;
|
||||
ExtendedType _extendedType;
|
||||
|
||||
public:
|
||||
|
||||
Token() :
|
||||
_string(""),
|
||||
_bool(false),
|
||||
_line(0),
|
||||
_character(0),
|
||||
_bytePosition(0),
|
||||
_type(END),
|
||||
_extendedType(END_TYPE) {}
|
||||
|
||||
Token(Type t, ExtendedType e, const std::string& s, int L, int c, uint64 byte)
|
||||
: _string(s), _bool(false), _line(L), _character(c), _bytePosition(byte), _type(t), _extendedType(e) {}
|
||||
|
||||
Token(Type t, ExtendedType e, const std::string& s, bool b, int L, int c, uint64 byte)
|
||||
: _string(s), _bool(b), _line(L), _character(c), _bytePosition(byte), _type(t), _extendedType(e) {}
|
||||
|
||||
Type type() const {
|
||||
return _type;
|
||||
}
|
||||
|
||||
ExtendedType extendedType() const {
|
||||
return _extendedType;
|
||||
}
|
||||
|
||||
/**
|
||||
The value of a single or double quote string (not including the quotes),
|
||||
the name of a symbol, or the exact textual representation of a number as
|
||||
parsed from the input.
|
||||
*/
|
||||
const std::string& string() const {
|
||||
return _string;
|
||||
}
|
||||
|
||||
bool boolean() const {
|
||||
return _bool;
|
||||
}
|
||||
|
||||
/**
|
||||
Starting line of the input from which this token was parsed. Starts
|
||||
at 1.
|
||||
*/
|
||||
int line() const {
|
||||
return _line;
|
||||
}
|
||||
|
||||
/**
|
||||
Starting character position in the input line from which this token was
|
||||
parsed. Starts at 1.
|
||||
*/
|
||||
int character() const {
|
||||
return _character;
|
||||
}
|
||||
|
||||
/** Number of bytes from the beginning of the buffer that this token was parsed from.
|
||||
Begins at 0 */
|
||||
uint64 bytePosition() const {
|
||||
return _bytePosition;
|
||||
}
|
||||
|
||||
/** Return the numeric value for a number type, or zero if this is
|
||||
not a number type.
|
||||
*/
|
||||
double number() const;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
\brief A simple tokenizer for parsing text files.
|
||||
|
||||
TextInput handles a
|
||||
superset of C++,Java, Matlab, and Bash code text including single
|
||||
line comments, block comments, quoted strings with escape sequences,
|
||||
and operators. TextInput recognizes several categories of tokens,
|
||||
which are separated by white space, quotation marks, or the end of a
|
||||
recognized operator:
|
||||
|
||||
<ul>
|
||||
<li><CODE>Token::SINGLE_QUOTED_TYPE</CODE> string of characters surrounded by single quotes, e.g., 'x', '\\0', 'foo'.
|
||||
<li><CODE>Token::DOUBLE_QUOTED_TYPE</CODE> string of characters surrounded by double quotes, e.g., "x", "abc\txyz", "b o b".
|
||||
<li><CODE>Token::SYMBOL_TYPE</CODE> legal C++ operators, keywords, and identifiers. e.g., >=, Foo, _X, class, {
|
||||
<li><CODE>Token::INTEGER_TYPE</CODE> numbers without decimal places or exponential notation. e.g., 10, 0x17F, 32, 0, -155
|
||||
<li><CODE>Token::FLOATING_POINT_TYPE</CODE> numbers with decimal places or exponential notation. e.g., 1e3, -1.2, .4, 0.5
|
||||
<li><CODE>Token::BOOLEAN_TYPE</CODE> special symbols like "true" and "false"; the exact details can be configured in TextInput::Settings
|
||||
<li><CODE>Token::LINE_COMMENT_TYPE</CODE> (disabled by default); generated for line comments as specified by TextInput::Settings
|
||||
<li><CODE>Token::BLOCK_COMMENT_TYPE</CODE> (disabled by default); generated for c-style block comments as specified by TextInput::Settings
|
||||
<li><CODE>Token::NEWLINE_TYPE</CODE> (disabled by default); generated for any of "\\r", "\\n" or "\\r\\n"
|
||||
</ul>
|
||||
|
||||
<P>The special ".." and "..." tokens are always recognized in
|
||||
addition to normal C++ operators. Additional tokens can be made
|
||||
available by changing the Settings.
|
||||
|
||||
Negative numbers are handled specially because of the ambiguity between unary minus and negative numbers--
|
||||
see the note on TextInput::read.
|
||||
|
||||
TextInput does not have helper functions for types with non-obvious
|
||||
formatting, or helpers that would be redundant. Use the serialize
|
||||
methods instead for parsing specific types like int, Vector3, and
|
||||
Color3.
|
||||
|
||||
Inside quoted strings escape sequences are converted. Thus the
|
||||
string token for ["a\\nb"] is 'a', followed by a newline, followed by
|
||||
'b'. Outside of quoted strings, escape sequences are not converted,
|
||||
so the token sequence for [a\\nb] is symbol 'a', symbol '\\', symbol
|
||||
'nb' (this matches what a C++ parser would do). The exception is
|
||||
that a specified TextInput::Settings::otherCommentCharacter preceeded
|
||||
by a backslash is assumed to be an escaped comment character and is
|
||||
returned as a symbol token instead of being parsed as a comment
|
||||
(this is what a LaTex or VRML parser would do).
|
||||
|
||||
<B>Examples</B>
|
||||
|
||||
\code
|
||||
TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
|
||||
|
||||
Token t;
|
||||
|
||||
t = ti.read();
|
||||
debugAssert(t.type == Token::SYMBOL);
|
||||
debugAssert(t.sval == "name");
|
||||
|
||||
ti.read();
|
||||
debugAssert(t.type == Token::SYMBOL);
|
||||
debugAssert(t.sval == "=");
|
||||
|
||||
std::string name = ti.read().sval;
|
||||
ti.read();
|
||||
\endcode
|
||||
|
||||
\code
|
||||
TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
|
||||
ti.readSymbols("name", "=");
|
||||
std::string name = ti.readString();
|
||||
ti.readSymbols(",", "height", "=");
|
||||
double height = ti. readNumber();
|
||||
\endcode
|
||||
|
||||
Assumes that the file is not modified once opened.
|
||||
*/
|
||||
class TextInput {
|
||||
public:
|
||||
/** Includes MSVC specials parsing */
|
||||
static double parseNumber(const std::string& _string);
|
||||
|
||||
/** toLower(_string) == "true" */
|
||||
static bool parseBoolean(const std::string& _string);
|
||||
|
||||
|
||||
/** Tokenizer configuration options. */
|
||||
class Settings {
|
||||
public:
|
||||
/** If true, C-style slash-star marks a multi-line comment.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool cppBlockComments;
|
||||
|
||||
/** If true, // begins a single line comment.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool cppLineComments;
|
||||
|
||||
/** If true, otherCommentCharacter and otherCommentCharacter2
|
||||
are used to begin single line comments in the same way
|
||||
cppLineComments is.
|
||||
|
||||
See generateCommentTokens for rules on how this is applied.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool otherLineComments;
|
||||
|
||||
/** If true, \\r, \\n, \\t, \\0, \\\\ and other escape sequences inside
|
||||
strings are converted to the equivalent C++ escaped character.
|
||||
If false, backslashes are treated literally. It is convenient to
|
||||
set to false if reading Windows paths, for example, like
|
||||
c:\\foo\\bar.
|
||||
|
||||
Default is true.
|
||||
*/
|
||||
bool escapeSequencesInStrings;
|
||||
|
||||
/** If not '\\0', specifies a character that begins single line
|
||||
comments ('#' and '%' are popular choices). This is independent
|
||||
of the cppLineComments flag. If the character appears in text with
|
||||
a backslash in front of it, it is considered escaped and is not
|
||||
treated as a comment character.
|
||||
|
||||
Default is '\\0'.
|
||||
*/
|
||||
char otherCommentCharacter;
|
||||
|
||||
/** Another (optional) 1-comment character. Useful for files that
|
||||
support multiple comment syntaxes. Default is '\\0'.
|
||||
*/
|
||||
char otherCommentCharacter2;
|
||||
|
||||
/** If true, comments enabled by cppBlockComments, cppLineComments
|
||||
and otherLineComments will generate their respective tokens.
|
||||
If false, the same settings will enable parsing and ignoring
|
||||
comments
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool generateCommentTokens;
|
||||
|
||||
/** If true, newlines will generate tokens.
|
||||
If false, newlines will be discarded as whitespace when parsed
|
||||
outside of other tokens.
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool generateNewlineTokens;
|
||||
|
||||
/** If true, "-1" parses as the number -1 instead of the
|
||||
symbol "-" followed by the number 1. Default is true.*/
|
||||
bool signedNumbers;
|
||||
|
||||
/** If true, strings can be marked with single quotes (e.g.,
|
||||
'aaa'). If false, the quote character is parsed as a
|
||||
symbol. Default is true. Backquote (`) is always parsed
|
||||
as a symbol. */
|
||||
bool singleQuotedStrings;
|
||||
|
||||
/** The character to use as a single quote. Defaults to "'" (backquote),
|
||||
occasionally useful to set to "`" (forward quote) or to "," (comma) for
|
||||
reading CSV files. */
|
||||
char singleQuoteCharacter;
|
||||
|
||||
/** If set to a non-empty string, that string will be used in
|
||||
place of the real file name (or in place of a pseudonym
|
||||
constructed from the buffer if given FROM_STRING) in
|
||||
tokens and exceptions.
|
||||
|
||||
Default is empty.
|
||||
*/
|
||||
std::string sourceFileName;
|
||||
|
||||
|
||||
/** Added to the line number reported by peekLineNumber and in
|
||||
exceptions. Useful for concatenating files that are
|
||||
parsed separately. Default is zero. */
|
||||
int startingLineNumberOffset;
|
||||
|
||||
/**
|
||||
Parse "-1.#IND00" as the floating point number returned by
|
||||
G3D::nan(), "-1.#INF00" as - G3D::inf(), and "1.#INF00" as G3D::inf().
|
||||
|
||||
Note that the C99 standard specifies that a variety of formats
|
||||
like "nan" are to be used; these are supported by
|
||||
G3D::TextInput::Settings::simpleFloatSpecials.
|
||||
|
||||
An alternative to specifying msvcFloatSpecials is to read numbers as:
|
||||
\htmlonly
|
||||
<pre>
|
||||
Token x = t.read();
|
||||
Token y = t.peek();
|
||||
if ((x.string() == "-1.") &&
|
||||
(y.string() == "#INF00") &&
|
||||
(y.character() == x.character() + 3) &&
|
||||
(y.line() == x.line()) {
|
||||
t.read();
|
||||
return nan();
|
||||
}
|
||||
// ... similar cases for inf
|
||||
</pre>
|
||||
\endhtmlonly
|
||||
|
||||
If the single-comment character was #, the floating point
|
||||
special format overrides the comment and will be parsed
|
||||
instead.
|
||||
|
||||
If signedNumbers is false msvcFloatSpecials will not be parsed.
|
||||
|
||||
Default is true. */
|
||||
bool msvcFloatSpecials;
|
||||
|
||||
/** Parses "+inf', "-inf", "inf", "nan" as floats instead of symbols.
|
||||
Defaults to true.*/
|
||||
bool simpleFloatSpecials;
|
||||
|
||||
/**
|
||||
Parse the following set of useful proof symbols:
|
||||
|
||||
=>
|
||||
::>
|
||||
<::
|
||||
:>
|
||||
<:
|
||||
|-
|
||||
::=
|
||||
:=
|
||||
<-
|
||||
|
||||
Default is false.
|
||||
*/
|
||||
bool proofSymbols;
|
||||
|
||||
/**
|
||||
When parsing booleans and msvcFloatSpecials, is case significant?
|
||||
Default is {true}
|
||||
*/
|
||||
bool caseSensitive;
|
||||
|
||||
/** All symbols that will become the 'true' boolean token. See also caseSensitive.
|
||||
Clear this value to disable parsing of true booleans.
|
||||
|
||||
Default is {true}.
|
||||
*/
|
||||
Set<std::string> trueSymbols;
|
||||
|
||||
/** See trueSymbols. Default is {false}*/
|
||||
Set<std::string> falseSymbols;
|
||||
|
||||
Settings();
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** \sa pushSettings / popSettings */
|
||||
Array<Settings> settingsStack;
|
||||
|
||||
std::deque<Token> stack;
|
||||
|
||||
/**
|
||||
Characters to be tokenized.
|
||||
*/
|
||||
Array<char> buffer;
|
||||
|
||||
/**
|
||||
Offset of current character (the next character to consumed) in
|
||||
input buffer.
|
||||
*/
|
||||
int currentCharOffset;
|
||||
|
||||
/**
|
||||
Line number of next character to be consumed from the input buffer. (1
|
||||
indicates first line of input.)
|
||||
|
||||
Note that this is the line number of the @e next character to be
|
||||
consumed from the input, not the line number of the @e last character
|
||||
consumed!
|
||||
*/
|
||||
int lineNumber;
|
||||
|
||||
/**
|
||||
Character number (within the line) of the next character to be consumed
|
||||
from the input buffer. (1 indicates first character of the line).
|
||||
|
||||
Note that this is the character number of the @e next character to be
|
||||
consumed from the input, not the character number of the @e last
|
||||
character consumed!
|
||||
*/
|
||||
int charNumber;
|
||||
|
||||
/** Configuration options. This includes the file name that will be
|
||||
reported in tokens and exceptions. */
|
||||
Settings options;
|
||||
|
||||
void init();
|
||||
|
||||
/**
|
||||
Consumes the next character from the input buffer, and returns that
|
||||
character. Updates lineNumber and charNumber to reflect the location of
|
||||
the next character in the input buffer.
|
||||
|
||||
Note: you shouldn't be using the return value of this function in most
|
||||
cases. In general, you should peekInputChar() to get the next
|
||||
character, determine what to do with it, then consume it with this
|
||||
function (or with eatAndPeekInputChar()). Given that usage, in most
|
||||
instances you already know what this function would return!
|
||||
*/
|
||||
int eatInputChar();
|
||||
|
||||
/**
|
||||
Returns the next character from the input buffer, without consuming any
|
||||
characters. Can also be used to look deeper into the input buffer.
|
||||
Does not modify lineNumber or charNumber.
|
||||
|
||||
@param distance Index of the character in the input buffer to peek at,
|
||||
relative to the next character. Default is 0, for the next character in
|
||||
the input buffer.
|
||||
*/
|
||||
int peekInputChar(int distance = 0);
|
||||
|
||||
/**
|
||||
Helper function to consume the next character in the input buffer and
|
||||
peek at the one following (without consuming it).
|
||||
*/
|
||||
inline int eatAndPeekInputChar() {
|
||||
eatInputChar();
|
||||
return peekInputChar(0);
|
||||
}
|
||||
|
||||
/**
|
||||
Read the next token, returning an END token if no more input is
|
||||
available.
|
||||
*/
|
||||
void nextToken(Token& t);
|
||||
|
||||
/**
|
||||
Helper for nextToken. Appends characters to t._string until the end
|
||||
delimiter is reached.
|
||||
|
||||
When called, the next character in the input buffer should be first the
|
||||
first character after the opening delimiter character.
|
||||
*/
|
||||
void parseQuotedString(unsigned char delimiter, Token& t);
|
||||
|
||||
void initFromString(const char* str, int len, const Settings& settings);
|
||||
|
||||
public:
|
||||
|
||||
class TokenException : public ParseError {
|
||||
public:
|
||||
/** Name of file being parsed when exception occurred.
|
||||
\deprecated Use filename
|
||||
*/
|
||||
std::string sourceFile;
|
||||
|
||||
virtual ~TokenException() {}
|
||||
|
||||
protected:
|
||||
|
||||
TokenException(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch);
|
||||
|
||||
};
|
||||
|
||||
/** While parsing a number of the form 1.\#IN?00, ? was
|
||||
not 'D' or 'F'. */
|
||||
class BadMSVCSpecial : public TokenException {
|
||||
public:
|
||||
|
||||
BadMSVCSpecial(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch);
|
||||
};
|
||||
|
||||
/** Thrown by the read methods. */
|
||||
class WrongTokenType : public TokenException {
|
||||
public:
|
||||
Token::Type expected;
|
||||
Token::Type actual;
|
||||
|
||||
WrongTokenType(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
Token::Type e,
|
||||
Token::Type a);
|
||||
};
|
||||
|
||||
class WrongSymbol : public TokenException {
|
||||
public:
|
||||
std::string expected;
|
||||
std::string actual;
|
||||
|
||||
WrongSymbol(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
const std::string& e,
|
||||
const std::string& a);
|
||||
};
|
||||
|
||||
|
||||
/** String read from input did not match expected string. */
|
||||
class WrongString : public TokenException {
|
||||
public:
|
||||
std::string expected;
|
||||
std::string actual;
|
||||
|
||||
WrongString(
|
||||
const std::string& src,
|
||||
int ln,
|
||||
int ch,
|
||||
const std::string& e,
|
||||
const std::string& a);
|
||||
};
|
||||
|
||||
TextInput(const std::string& filename, const Settings& settings = Settings());
|
||||
|
||||
enum FS {FROM_STRING};
|
||||
/** Creates input directly from a string. The first argument must be
|
||||
TextInput::FROM_STRING.
|
||||
*/
|
||||
TextInput(FS fs, const std::string& str, const Settings& settings = Settings());
|
||||
|
||||
/** Creates input directly from a fixed-length, non-NULL terminated string. The first argument must be
|
||||
TextInput::FROM_STRING.
|
||||
*/
|
||||
TextInput(FS fs, const char* str, size_t strLen, const Settings& settings = Settings());
|
||||
|
||||
/** Returns true while there are tokens remaining. */
|
||||
bool hasMore();
|
||||
|
||||
/** Temporarily switch parsing to use \a settings. Note that this will override the currently recorded sourceFilename unless you explicitly set it back.
|
||||
\sa popSettings */
|
||||
void pushSettings(const Settings& settings) {
|
||||
settingsStack.push(options);
|
||||
options = settings;
|
||||
}
|
||||
|
||||
void popSettings() {
|
||||
options = settingsStack.pop();
|
||||
}
|
||||
|
||||
/** Read the next token (which will be the END token if ! hasMore()).
|
||||
|
||||
Signed numbers can be handled in one of two modes. If the option
|
||||
TextInput::Settings::signedNumbers is true,
|
||||
A '+' or '-' immediately before a number is prepended onto that number and
|
||||
if there is intervening whitespace, it is read as a separate symbol.
|
||||
|
||||
If TextInput::Settings::signedNumbers is false,
|
||||
read() does not distinguish between a plus or minus symbol next
|
||||
to a number and a positive/negative number itself. For example, "x - 1" and "x -1"
|
||||
will be parsed the same way by read().
|
||||
|
||||
In both cases, readNumber() will contract a leading "-" or "+" onto
|
||||
a number.
|
||||
*/
|
||||
Token read();
|
||||
|
||||
/** Avoids the copy of read() */
|
||||
void read(Token& t);
|
||||
|
||||
/** Calls read() until the result is not a newline or comment */
|
||||
Token readSignificant();
|
||||
|
||||
/** Read one token (or possibly two, for minus sign) as a number or throws
|
||||
WrongTokenType, and returns the number.
|
||||
|
||||
If the first token in the input is a number, it is returned directly.
|
||||
|
||||
If TextInput::Settings::signedNumbers is false and the input stream
|
||||
contains a '+' or '-' symbol token immediately followed by a number
|
||||
token, both tokens will be consumed and a single token will be
|
||||
returned by this method.
|
||||
|
||||
WrongTokenType will be thrown if one of the input conditions
|
||||
described above is not satisfied. When an exception is thrown, no
|
||||
tokens are consumed.
|
||||
*/
|
||||
double readNumber();
|
||||
|
||||
/** Reads a number that must be in C integer format:
|
||||
<code> [ '+' | '-' ] #+ | '0x'#+</code> */
|
||||
int readInteger();
|
||||
|
||||
bool readBoolean();
|
||||
|
||||
/** Reads a string token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readString) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a string. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readStringToken();
|
||||
|
||||
/** Like readStringToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readStringToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readStringToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readString();
|
||||
|
||||
/** Reads a specific string token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a string matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific string from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a string. WrongString will be thrown if the next token in the
|
||||
input stream is a string but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
|
||||
\sa readString(), readStringToken(), readUntilNewlineAsString(), readUntilDelimiterAsString()
|
||||
*/
|
||||
void readString(const std::string& s);
|
||||
|
||||
/** Read from the beginning of the next token until the following newline
|
||||
and return the result as a string, ignoring all parsing in between. The newline
|
||||
is not returned in the string, and the following token read will be a newline or
|
||||
end of file token (if they are enabled for parsing).*/
|
||||
std::string readUntilNewlineAsString();
|
||||
|
||||
/** Read from the beginning of the next token until the following delimiter character
|
||||
and return the result as a string, ignoring all parsing in between. The delimiter
|
||||
is not returned in the string, and the following token read will begin at the delimiter or
|
||||
end of file token (if they are enabled for parsing).*/
|
||||
std::string readUntilDelimiterAsString(const char delimiter1, const char delimiter2 = '\0');
|
||||
|
||||
/** Reads a comment token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readComment) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a comment. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readCommentToken();
|
||||
|
||||
/** Like readCommentToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readCommentToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readCommentToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readComment();
|
||||
|
||||
/** Reads a specific comment token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a comment matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific comment from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a comment. WrongString will be thrown if the next token in the
|
||||
input stream is a comment but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readComment(const std::string& s);
|
||||
|
||||
/** Reads a newline token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readNewline) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a newline. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readNewlineToken();
|
||||
|
||||
/** Like readNewlineToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readNewlineToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readNewlineToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readNewline();
|
||||
|
||||
/** Reads a specific newline token or throws either WrongTokenType or
|
||||
WrongString. If the next token in the input is a newline matching @p
|
||||
s, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific newline from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a newline. WrongString will be thrown if the next token in the
|
||||
input stream is a newlin but does not match the @p s parameter. When
|
||||
an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readNewline(const std::string& s);
|
||||
|
||||
/** Reads a symbol token or throws WrongTokenType, and returns the token.
|
||||
|
||||
Use this method (rather than readSymbol) if you want the token's
|
||||
location as well as its value.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a symbol. When an exception is thrown, no tokens are
|
||||
consumed.
|
||||
*/
|
||||
Token readSymbolToken();
|
||||
|
||||
/** Avoids the copy of readSymbolToken() */
|
||||
void readSymbolToken(Token& t);
|
||||
|
||||
/** Like readSymbolToken, but returns the token's string.
|
||||
|
||||
Use this method (rather than readSymbolToken) if you want the token's
|
||||
value but don't really care about its location in the input. Use of
|
||||
readSymbolToken is encouraged for better error reporting.
|
||||
*/
|
||||
std::string readSymbol();
|
||||
|
||||
/** Reads a specific symbol token or throws either WrongTokenType or
|
||||
WrongSymbol. If the next token in the input is a symbol matching @p
|
||||
symbol, it will be consumed.
|
||||
|
||||
Use this method if you want to match a specific symbol from the
|
||||
input. In that case, typically error reporting related to the token
|
||||
is only going to occur because of a mismatch, so no location
|
||||
information is needed by the caller.
|
||||
|
||||
WrongTokenType will be thrown if the next token in the input stream
|
||||
is not a symbol. WrongSymbol will be thrown if the next token in the
|
||||
input stream is a symbol but does not match the @p symbol parameter.
|
||||
When an exception is thrown, no tokens are consumed.
|
||||
*/
|
||||
void readSymbol(const std::string& symbol);
|
||||
|
||||
|
||||
/** Read a series of two specific symbols. See readSymbol. */
|
||||
void readSymbols(const std::string& s1, const std::string& s2) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
}
|
||||
|
||||
/** Read a series of three specific symbols. See readSymbol. */
|
||||
void readSymbols(
|
||||
const std::string& s1,
|
||||
const std::string& s2,
|
||||
const std::string& s3) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
readSymbol(s3);
|
||||
}
|
||||
|
||||
/** Read a series of four specific symbols. See readSymbol. */
|
||||
void readSymbols(
|
||||
const std::string& s1,
|
||||
const std::string& s2,
|
||||
const std::string& s3,
|
||||
const std::string& s4) {
|
||||
readSymbol(s1);
|
||||
readSymbol(s2);
|
||||
readSymbol(s3);
|
||||
readSymbol(s4);
|
||||
}
|
||||
|
||||
/** Return a copy of the next token in the input stream, but don't remove
|
||||
it from the input stream.
|
||||
*/
|
||||
Token peek();
|
||||
|
||||
/** Returns the line number for the @e next token. See also peek. */
|
||||
int peekLineNumber();
|
||||
|
||||
/** Returns the character number (relative to the line) for the @e next
|
||||
token in the input stream. See also peek.
|
||||
*/
|
||||
int peekCharacterNumber();
|
||||
|
||||
/** Take a previously read token and push it back at the front of the
|
||||
input stream.
|
||||
|
||||
Can be used in the case where more than one token of read-ahead is
|
||||
needed (i.e., when peek doesn't suffice).
|
||||
*/
|
||||
void push(const Token& t);
|
||||
|
||||
/** Returns the filename from which this input is drawn, or the first few
|
||||
characters of the string if created from a string.
|
||||
If settings::filename is non-empty that will replace the
|
||||
true filename.*/
|
||||
const std::string& filename() const;
|
||||
};
|
||||
|
||||
void deserialize(bool& b, TextInput& ti);
|
||||
void deserialize(int& b, TextInput& ti);
|
||||
void deserialize(uint8& b, TextInput& ti);
|
||||
void deserialize(double& b, TextInput& ti);
|
||||
void deserialize(float& b, TextInput& ti);
|
||||
void deserialize(std::string& b, TextInput& ti);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif
|
||||
|
||||
262
dep/g3dlite/include/G3D/TextOutput.h
Normal file
262
dep/g3dlite/include/G3D/TextOutput.h
Normal file
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
\file G3D/TextOutput.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
\created 2004-06-21
|
||||
\edited 2011-05-24
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_TextOutput_h
|
||||
#define G3D_TextOutput_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
Convenient formatting of ASCII text written to a file.
|
||||
<P>
|
||||
|
||||
The core writeString, writeNumber, and writeSymbol methods map to TextInput's
|
||||
methods. Number and Symbol each print an additional space that is used to
|
||||
separate adjacent tokens.
|
||||
|
||||
TextOutput::printf allows arbitrary text to be conveniently dumped
|
||||
en-masse. Use [de]serialize(bool, TextOutput) and other overloads to read/write
|
||||
primitive types in a standardized manner and
|
||||
|
||||
<P>
|
||||
When a word-wrap line break occurs, all whitespace between words is replaced
|
||||
with a single newline (the newline may be two characters-- see
|
||||
G3D::TextOutput::Options::NewlineStyle). Word wrapping occurs against
|
||||
the number of columns specified by Options::numColumns, <I>minus</I> the current
|
||||
indent level.
|
||||
|
||||
Indenting adds the specified number of spaces immediately after a newline.
|
||||
If a newline was followed by spaces in the original string, these are added
|
||||
to the indent spaces. Indenting <B>will</B> indent blank lines and will leave
|
||||
indents after the last newline of a file (if the indent level is non-zero at the end).
|
||||
|
||||
<P><B>Serialization/Marshalling</B>
|
||||
<DT>Text serialization is accomplished using TextOutput by defining the pair of
|
||||
methods:
|
||||
|
||||
<PRE>
|
||||
void serialize(TextOutput& to) const;
|
||||
void deserialize(TextInput& ti);
|
||||
</PRE>
|
||||
|
||||
See also G3D::TextInput.
|
||||
|
||||
<P>
|
||||
<B>BETA API</B>
|
||||
<DT>This API is subject to change in future versions.
|
||||
*/
|
||||
class TextOutput {
|
||||
public:
|
||||
|
||||
class Settings {
|
||||
public:
|
||||
/**
|
||||
WRAP_NONE Word wrapping is disabled
|
||||
WRAP_WITHOUT_BREAKING Word-wrap, but don't break continuous lines that
|
||||
are longer than numColumns (default)
|
||||
WRAP_ALWAYS Wrap even if it means breaking a continuous line or
|
||||
a quoted string.
|
||||
|
||||
Word wrapping is only allowed at whitespaces ('\\n', '\\r', '\\t', ' '); it
|
||||
will not occur after commas, punctuation, minus signs, or any other characters
|
||||
*/
|
||||
enum WordWrapMode {WRAP_NONE, WRAP_WITHOUT_BREAKING, WRAP_ALWAYS};
|
||||
|
||||
/** Defaults to WRAP_WITHOUT_BREAKING */
|
||||
WordWrapMode wordWrap;
|
||||
|
||||
/** Is word-wrapping allowed to insert newlines inside double quotes?
|
||||
Default: false */
|
||||
bool allowWordWrapInsideDoubleQuotes;
|
||||
|
||||
/** Number of columns for word wrapping. Default: 8 */
|
||||
int numColumns;
|
||||
|
||||
/** Number of spaces in each indent. Default: 4 */
|
||||
int spacesPerIndent;
|
||||
|
||||
/** Style of newline used by word wrapping and by (optional) conversion.
|
||||
default: Windows: NEWLINE_WINDOWS, Linux, OS X: NEWLINE_UNIX.
|
||||
*/
|
||||
enum NewlineStyle {NEWLINE_WINDOWS, NEWLINE_UNIX};
|
||||
|
||||
NewlineStyle newlineStyle;
|
||||
|
||||
/** If true, all newlines are converted to NewlineStyle regardless of
|
||||
how they start out. Default: true. */
|
||||
bool convertNewlines;
|
||||
|
||||
/** Used by writeBoolean */
|
||||
std::string trueSymbol;
|
||||
|
||||
/** Used by writeBoolean */
|
||||
std::string falseSymbol;
|
||||
|
||||
Settings() :
|
||||
wordWrap(WRAP_WITHOUT_BREAKING),
|
||||
allowWordWrapInsideDoubleQuotes(false),
|
||||
numColumns(80),
|
||||
spacesPerIndent(4),
|
||||
convertNewlines(true),
|
||||
trueSymbol("true"),
|
||||
falseSymbol("false") {
|
||||
#ifdef G3D_WINDOWS
|
||||
newlineStyle = NEWLINE_WINDOWS;
|
||||
#else
|
||||
newlineStyle = NEWLINE_UNIX;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
/** Used by indentAndAppend to tell when we are writing the
|
||||
first character of a new line.
|
||||
|
||||
So that push/popIndent work correctly, we cannot indent
|
||||
immediately after writing a newline. Instead we must
|
||||
indent on writing the first character <B>after</B> that
|
||||
newline.
|
||||
*/
|
||||
bool startingNewLine;
|
||||
|
||||
/** Number of characters at the end of the buffer since the last newline */
|
||||
int currentColumn;
|
||||
|
||||
/** True if we have seen an open " and no close ".*/
|
||||
bool inDQuote;
|
||||
|
||||
/** Empty if there is none */
|
||||
std::string filename;
|
||||
|
||||
Array<char> data;
|
||||
|
||||
Settings option;
|
||||
|
||||
/** Number of indents to prepend before each line. Always set using setIndentLevel.*/
|
||||
int indentLevel;
|
||||
|
||||
void setIndentLevel(int i);
|
||||
|
||||
/** Actual number of spaces to indent. */
|
||||
int indentSpaces;
|
||||
|
||||
/** the newline character(s) */
|
||||
std::string newline;
|
||||
|
||||
/** Starts at 1 */
|
||||
int m_currentLine;
|
||||
|
||||
void setOptions(const Settings& _opt);
|
||||
|
||||
/** Converts to the desired newlines. Called from vprintf */
|
||||
void convertNewlines(const std::string& in, std::string& out);
|
||||
|
||||
/** Called from vprintf */
|
||||
void wordWrapIndentAppend(const std::string& str);
|
||||
|
||||
/** Appends the character to data, indenting whenever a newline is encountered.
|
||||
Called from wordWrapIndentAppend */
|
||||
void indentAppend(char c);
|
||||
|
||||
public:
|
||||
|
||||
explicit TextOutput(const std::string& filename, const Settings& options = Settings());
|
||||
|
||||
/** Constructs a text output that can later be commited to a string instead of a file.*/
|
||||
explicit TextOutput(const Settings& options = Settings());
|
||||
|
||||
/** Returns one plus the number of newlines written since the output was created. */
|
||||
int line() const {
|
||||
return m_currentLine;
|
||||
}
|
||||
|
||||
/** Commit to the filename specified on the constructor.
|
||||
<B>Not</B> called from the destructor; you must call
|
||||
it yourself.
|
||||
@param flush If true (default) the file is ready for reading when the method returns, otherwise
|
||||
the method returns immediately and writes the file in the background.*/
|
||||
void commit(bool flush = true);
|
||||
|
||||
/** Commits to this string */
|
||||
void commitString(std::string& string);
|
||||
|
||||
/** Increase indent level by 1 */
|
||||
void pushIndent();
|
||||
|
||||
void popIndent();
|
||||
|
||||
/** Produces a new string that contains the output */
|
||||
std::string commitString();
|
||||
|
||||
/** Writes a quoted string. Special characters in the string (e.g., \\, \\t, \\n) are escaped so that
|
||||
TextInput will produce the identical string on reading.*/
|
||||
void writeString(const std::string& string);
|
||||
|
||||
void writeBoolean(bool b);
|
||||
|
||||
void writeNumber(double n);
|
||||
|
||||
void writeNumber(int n);
|
||||
|
||||
void writeNewline();
|
||||
void writeNewlines(int numLines);
|
||||
|
||||
/** If the most recently written character was a space, remove it and return true. Can be called repeatedly to back up over multiple spaces. */
|
||||
bool deleteSpace();
|
||||
|
||||
/** The symbol is written without quotes. Symbols are required to begin with a
|
||||
letter or underscore and contain only letters, underscores, and numbers
|
||||
or be a C++ symbol (e.g. "{", "(", "++", etc.)
|
||||
so that they may be properly parsed by TextInput::readSymbol. Symbols are
|
||||
printed with a trailing space.*/
|
||||
void writeSymbol(const std::string& string);
|
||||
|
||||
void writeSymbol(char s);
|
||||
|
||||
/** Convenient idiom for writing multiple symbols in a row, e.g.
|
||||
writeSymbols("name", "="); The empty symbols are not written.
|
||||
*/
|
||||
void writeSymbols(
|
||||
const std::string& a,
|
||||
const std::string& b = "",
|
||||
const std::string& c = "",
|
||||
const std::string& d = "",
|
||||
const std::string& e = "",
|
||||
const std::string& f = "");
|
||||
|
||||
/** Normal printf conventions. Note that the output will be reformatted
|
||||
for word-wrapping and newlines */
|
||||
void __cdecl printf(const char* fmt, ...)
|
||||
G3D_CHECK_PRINTF_METHOD_ARGS;
|
||||
|
||||
// Can't pass by reference because that confuses va_start
|
||||
void __cdecl printf(const std::string fmt, ...);
|
||||
void __cdecl vprintf(const char* fmt, va_list argPtr)
|
||||
G3D_CHECK_VPRINTF_METHOD_ARGS;
|
||||
};
|
||||
|
||||
// Primitive serializers
|
||||
void serialize(const bool& b, TextOutput& to);
|
||||
void serialize(const int& b, TextOutput& to);
|
||||
void serialize(const uint8& b, TextOutput& to);
|
||||
void serialize(const double& b, TextOutput& to);
|
||||
void serialize(const float& b, TextOutput& to);
|
||||
void serialize(const std::string& b, TextOutput& to);
|
||||
void serialize(const char* b, TextOutput& to);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
90
dep/g3dlite/include/G3D/ThreadSet.h
Normal file
90
dep/g3dlite/include/G3D/ThreadSet.h
Normal file
@@ -0,0 +1,90 @@
|
||||
#ifndef G3D_ThreadSet_h
|
||||
#define G3D_ThreadSet_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Array.h"
|
||||
#include "G3D/ReferenceCount.h"
|
||||
#include "G3D/GMutex.h"
|
||||
#include "G3D/SpawnBehavior.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class GThread;
|
||||
|
||||
/** Manages a set of threads. All methods are threadsafe except for
|
||||
the iterator begin/end.
|
||||
|
||||
@beta*/
|
||||
class ThreadSet : public ReferenceCountedObject {
|
||||
public:
|
||||
/** Intended to allow future use with a template parameter.*/
|
||||
typedef GThread Thread;
|
||||
|
||||
typedef shared_ptr<Thread> ThreadRef;
|
||||
typedef shared_ptr<ThreadSet> Ref;
|
||||
typedef Array<ThreadRef>::Iterator Iterator;
|
||||
typedef Array<ThreadRef>::ConstIterator ConstIterator;
|
||||
|
||||
private:
|
||||
|
||||
/** Protects m_thread */
|
||||
GMutex m_lock;
|
||||
|
||||
/** Threads in the set */
|
||||
Array<ThreadRef> m_thread;
|
||||
|
||||
public:
|
||||
|
||||
/** Total number of threads (some of which may be completed). */
|
||||
int size() const;
|
||||
|
||||
/** Number of threads that have been started */
|
||||
int numStarted() const;
|
||||
|
||||
/** Start all threads that are not currently started.
|
||||
|
||||
@param lastThreadBehavior If USE_CURRENT_THREAD, takes the
|
||||
last unstarted thread and executes it manually on the current
|
||||
thread. This helps to take full advantage of the machine when
|
||||
running a large number of jobs and avoids the overhead of a
|
||||
thread start for single-thread groups. Note that this forces
|
||||
start() to block until that thread is complete.
|
||||
*/
|
||||
void start(SpawnBehavior lastThreadBehavior = USE_NEW_THREAD) const;
|
||||
|
||||
/** Terminate all threads that are currently started */
|
||||
void terminate() const;
|
||||
|
||||
/** Waits until all started threads have completed. */
|
||||
void waitForCompletion() const;
|
||||
|
||||
/** Remove all (not stopping them) */
|
||||
void clear();
|
||||
|
||||
/** Removes completed threads and returns the new size.*/
|
||||
int removeCompleted();
|
||||
|
||||
/** Inserts a new thread, if it is not already present, and
|
||||
returns the new number of threads.*/
|
||||
int insert(const ThreadRef& t);
|
||||
|
||||
/** Removes a thread. Returns true if the thread was present and
|
||||
removed. */
|
||||
bool remove(const ThreadRef& t);
|
||||
|
||||
bool contains(const ThreadRef& t) const;
|
||||
|
||||
/** It is an error to mutate the ThreadSet while iterating through it. */
|
||||
Iterator begin();
|
||||
|
||||
Iterator end();
|
||||
|
||||
ConstIterator begin() const;
|
||||
|
||||
ConstIterator end() const;
|
||||
};
|
||||
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
#endif
|
||||
160
dep/g3dlite/include/G3D/Triangle.h
Normal file
160
dep/g3dlite/include/G3D/Triangle.h
Normal file
@@ -0,0 +1,160 @@
|
||||
/**
|
||||
\file G3D/Triangle.h
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2003-04-05
|
||||
\edited 2011-06-20
|
||||
|
||||
\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-2012, 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 "G3D/BoundsTrait.h"
|
||||
#include "G3D/debugAssert.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];
|
||||
float 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(class BinaryInput& b);
|
||||
void serialize(class BinaryOutput& b);
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
Triangle();
|
||||
|
||||
Triangle(const Point3& v0, const Point3& v1, const Point3& v2);
|
||||
|
||||
~Triangle();
|
||||
|
||||
/** 0, 1, or 2 */
|
||||
inline const Point3& vertex(int n) const {
|
||||
debugAssert((n >= 0) && (n < 3));
|
||||
return _vertex[n];
|
||||
}
|
||||
|
||||
/** vertex[1] - vertex[0] */
|
||||
inline const Vector3& edge01() const {
|
||||
return _edge01;
|
||||
}
|
||||
|
||||
/** vertex[2] - vertex[0] */
|
||||
inline const Vector3& edge02() const {
|
||||
return _edge02;
|
||||
}
|
||||
|
||||
float area() const;
|
||||
|
||||
Vector3::Axis primaryAxis() const {
|
||||
return _primaryAxis;
|
||||
}
|
||||
|
||||
const Vector3& normal() const;
|
||||
|
||||
/** Barycenter */
|
||||
Point3 center() const;
|
||||
|
||||
const Plane& plane() const;
|
||||
|
||||
/** Returns a random point in the triangle. */
|
||||
Point3 randomPoint() const;
|
||||
|
||||
inline void getRandomSurfacePoint
|
||||
(Point3& P,
|
||||
Vector3& N = Vector3::ignore()) const {
|
||||
P = randomPoint();
|
||||
N = normal();
|
||||
}
|
||||
|
||||
/**
|
||||
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 size_t hashCode() const {
|
||||
return
|
||||
_vertex[0].hashCode() +
|
||||
(_vertex[1].hashCode() >> 2) +
|
||||
(_vertex[2].hashCode() >> 3);
|
||||
}
|
||||
|
||||
void getBounds(class AABox&) const;
|
||||
|
||||
/**
|
||||
@brief Intersect the ray at distance less than @a distance.
|
||||
|
||||
@param distance Set to the maximum distance (can be G3D::inf())
|
||||
to search for an intersection. On return, this is the smaller
|
||||
of the distance to the intersection, if one exists, and the original
|
||||
value.
|
||||
|
||||
@param baryCoord If a triangle is hit before @a distance, a
|
||||
the barycentric coordinates of the hit location on the triangle.
|
||||
Otherwise, unmodified.
|
||||
|
||||
@return True if there was an intersection before the original distance.
|
||||
*/
|
||||
bool intersect(const class Ray& ray, float& distance, float baryCoord[3]) const;
|
||||
};
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
template <> struct HashTrait<G3D::Triangle> {
|
||||
static size_t hashCode(const G3D::Triangle& key) { return key.hashCode(); }
|
||||
};
|
||||
|
||||
|
||||
template<> struct BoundsTrait<class G3D::Triangle> {
|
||||
static void getBounds(const G3D::Triangle& t, G3D::AABox& out) { t.getBounds(out); }
|
||||
};
|
||||
|
||||
#endif
|
||||
117
dep/g3dlite/include/G3D/UprightFrame.h
Normal file
117
dep/g3dlite/include/G3D/UprightFrame.h
Normal file
@@ -0,0 +1,117 @@
|
||||
/**
|
||||
\file G3D/UprightFrame.h
|
||||
\author Morgan McGuire, http://graphics.cs.williams.edu
|
||||
*/
|
||||
|
||||
#ifndef G3D_UprightFrame_h
|
||||
#define G3D_UprightFrame_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/Spline.h"
|
||||
#include "G3D/Any.h"
|
||||
#include "G3D/CoordinateFrame.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\brief Coordinate frame expressed in Euler angles.
|
||||
Unlike a G3D::Quat, UprightFrame always keeps the reference frame from rolling about its own z axis.
|
||||
Particularly useful for cameras.
|
||||
|
||||
\sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator
|
||||
*/
|
||||
class UprightFrame {
|
||||
public:
|
||||
|
||||
Vector3 translation;
|
||||
|
||||
/** -pi/2 < pitch < pi/2 in radians about the X-axis */
|
||||
float pitch;
|
||||
|
||||
/** In radians about the Y-axis */
|
||||
float yaw;
|
||||
|
||||
UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0)
|
||||
: translation(t), pitch(p), yaw(y) {}
|
||||
|
||||
UprightFrame(const CoordinateFrame& cframe);
|
||||
|
||||
/** Constructs an UprightFrame from an Any object.
|
||||
|
||||
The Any format for UprightFrame is:
|
||||
|
||||
pitch = ##,
|
||||
translation = Vector3(),
|
||||
yaw = ##
|
||||
*/
|
||||
explicit UprightFrame(const Any& any);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
UprightFrame& operator=(const Any& any);
|
||||
|
||||
/** Supports implicit cast to CoordinateFrame */
|
||||
operator CoordinateFrame() const {
|
||||
return toCoordinateFrame();
|
||||
}
|
||||
|
||||
CoordinateFrame toCoordinateFrame() const;
|
||||
|
||||
/** Required for use with spline */
|
||||
UprightFrame operator+(const UprightFrame& other) const;
|
||||
|
||||
/** Required for use with spline */
|
||||
UprightFrame operator*(const float k) const;
|
||||
|
||||
/**
|
||||
Unwraps the yaw values in the elements of the array such that
|
||||
they still represent the same angles but strictly increase/decrease
|
||||
without wrapping about zero. For use with Spline<UprightFrame>
|
||||
*/
|
||||
static void unwrapYaw(UprightFrame* a, int N);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling.
|
||||
|
||||
\sa G3D::UprightSplineManipulator, G3D::UprightFrame
|
||||
*/
|
||||
class UprightSpline : public Spline<UprightFrame> {
|
||||
protected:
|
||||
|
||||
virtual void ensureShortestPath(UprightFrame* A, int N) const {
|
||||
UprightFrame::unwrapYaw(A, N);
|
||||
}
|
||||
|
||||
public:
|
||||
UprightSpline();
|
||||
|
||||
|
||||
/** Constructs an UprightSpline from an Any object.
|
||||
|
||||
The Any format for UprightSpline is:
|
||||
|
||||
controls = (UprightFrame, ...),
|
||||
times = (##, ...),
|
||||
cyclic = bool
|
||||
|
||||
The controls and times arrays must have the same length.
|
||||
*/
|
||||
explicit UprightSpline(const Any& any);
|
||||
|
||||
virtual Any toAny(const std::string& myName) const override;
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
UprightSpline& operator=(const Any& any);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
514
dep/g3dlite/include/G3D/Vector2.h
Normal file
514
dep/g3dlite/include/G3D/Vector2.h
Normal file
@@ -0,0 +1,514 @@
|
||||
/**
|
||||
\file G3D/Vector2.h
|
||||
|
||||
2D vector class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-06-02
|
||||
\edited 2011-11-30
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Vector2_h
|
||||
#define G3D_Vector2_h
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/Vector2int16.h"
|
||||
#include "G3D/Vector2unorm16.h"
|
||||
#include "G3D/Random.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector3;
|
||||
class Vector4;
|
||||
class Vector2int32;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
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:
|
||||
float x;
|
||||
float y;
|
||||
|
||||
/** \param any Must either Vector2(#, #) or Vector2 {x = #, y = #}*/
|
||||
Vector2(const Any& any);
|
||||
|
||||
/** Converts the Vector2 to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
/** Creates the zero vector */
|
||||
Vector2();
|
||||
Vector2(class TextInput& t);
|
||||
Vector2(class BinaryInput& b);
|
||||
Vector2(float x, float y);
|
||||
Vector2(float coordinate[2]);
|
||||
Vector2(double coordinate[2]);
|
||||
Vector2(const Vector2& other);
|
||||
Vector2(const Vector2int16& other);
|
||||
Vector2(const Vector2unorm16& other);
|
||||
|
||||
// explicit because of precision loss
|
||||
explicit Vector2(const Vector2int32& other);
|
||||
|
||||
Vector2& operator=(const Any& a);
|
||||
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
void serialize(class TextOutput& t) const;
|
||||
void deserialize(class TextInput& t);
|
||||
|
||||
float& operator[](int i);
|
||||
const float& operator[](int i) const;
|
||||
|
||||
// assignment and comparison
|
||||
Vector2& operator=(const Vector2& other);
|
||||
bool operator==(const Vector2& other) const;
|
||||
bool operator!=(const Vector2& other) const;
|
||||
size_t 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;
|
||||
|
||||
/** True if any field is NaN */
|
||||
bool isNaN() const {
|
||||
return G3D::isNaN(x) || G3D::isNaN(y);
|
||||
}
|
||||
|
||||
/** 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& v) const;
|
||||
Vector2 operator-(const Vector2& v) const;
|
||||
Vector2 operator*(float s) const;
|
||||
|
||||
/** Raise each component of this vector to a power */
|
||||
Vector2 pow(float p) const {
|
||||
return Vector2(powf(x, p), powf(y, p));
|
||||
}
|
||||
|
||||
/** Array (pointwise) multiplication */
|
||||
Vector2 operator*(const Vector2& v) const;
|
||||
|
||||
/** Array division */
|
||||
Vector2 operator/(const Vector2& v) const;
|
||||
Vector2 operator/(float s) const;
|
||||
|
||||
/** Unary minus */
|
||||
Vector2 operator-() const;
|
||||
|
||||
/** x + y */
|
||||
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&);
|
||||
Vector2& operator-=(const Vector2&);
|
||||
Vector2& operator*=(float);
|
||||
Vector2& operator/=(float);
|
||||
Vector2& operator*=(const Vector2&);
|
||||
Vector2& operator/=(const Vector2&);
|
||||
|
||||
// vector operations
|
||||
|
||||
/** Magnitude of the vector */
|
||||
float length() const;
|
||||
|
||||
/**
|
||||
Returns a unit-length version of this vector.
|
||||
Returns nan if length is almost zero.
|
||||
*/
|
||||
Vector2 direction() const;
|
||||
|
||||
/** Returns Vector2::zero() is magnitude is almost zero,
|
||||
otherwise returns unit-length vector. */
|
||||
Vector2 directionOrZero() 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& s) const;
|
||||
|
||||
/** Componentwise absolute value */
|
||||
Vector2 abs() const {
|
||||
return Vector2(fabs(x), fabs(y));
|
||||
}
|
||||
|
||||
/** Component-wise minimum */
|
||||
Vector2 min(const Vector2& v) const;
|
||||
|
||||
/** Component-wise maximum */
|
||||
Vector2 max(const Vector2& v) const;
|
||||
|
||||
/** Component-wise argmax(abs(), v.abs()).
|
||||
|
||||
For the larger magnitude vector, simply use <code>(a.squaredMagnitude() > b.squaredMagnitude) ? a : b</code>.
|
||||
\sa max
|
||||
*/
|
||||
Vector2 maxAbs(const Vector2& v) const {
|
||||
return Vector2(::fabsf(x) > ::fabsf(v.x) ? x : v.x, ::fabsf(y) > ::fabsf(v.y) ? y : v.y);
|
||||
}
|
||||
|
||||
/** Component-wise argmin(abs(), v.abs()).
|
||||
|
||||
For the smaller magnitude vector, simply use <code>(a.squaredMagnitude() < b.squaredMagnitude) ? a : b</code>.
|
||||
\sa max
|
||||
*/
|
||||
Vector2 minAbs(const Vector2& v) const {
|
||||
return Vector2(::fabsf(x) < ::fabsf(v.x) ? x : v.x, ::fabsf(y) < ::fabsf(v.y) ? y : v.y);
|
||||
}
|
||||
|
||||
/** Uniformly distributed random vector on the unit sphere */
|
||||
static Vector2 random(Random& r = Random::common());
|
||||
|
||||
// Special values.
|
||||
// Intentionally not inlined: see Matrix3::identity() for details.
|
||||
static const Vector2& zero();
|
||||
static const Vector2& one();
|
||||
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();
|
||||
|
||||
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 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 Vector2::Vector2 (const Vector2unorm16& v) : x(float(v.x)), y(float(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& 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 Vector2 Vector2::directionOrZero() const {
|
||||
float mag = length();
|
||||
if (mag < 0.0000001f) {
|
||||
return Vector2::zero();
|
||||
} else if (mag < 1.00001f && mag > 0.99999f) {
|
||||
return *this;
|
||||
} else {
|
||||
return *this * (1.0f / mag);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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 G3D::fuzzyEq(fabsf(x) + fabsf(y), 0.0f);
|
||||
}
|
||||
|
||||
|
||||
|
||||
inline bool Vector2::isUnit() const {
|
||||
return G3D::fuzzyEq(squaredLength(), 1.0f);
|
||||
}
|
||||
|
||||
typedef Vector2 Point2;
|
||||
void serialize(const Vector2& v, class BinaryOutput& b);
|
||||
void deserialize(Vector2& v, class BinaryInput& b);
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Vector2> {
|
||||
static size_t hashCode(const G3D::Vector2& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
#endif
|
||||
144
dep/g3dlite/include/G3D/Vector2int16.h
Normal file
144
dep/g3dlite/include/G3D/Vector2int16.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/**
|
||||
@file Vector2int16.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@brown.edu
|
||||
|
||||
@created 2003-08-09
|
||||
@edited 2010-01-03
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef Vector2int16_h
|
||||
#define Vector2int16_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
/**
|
||||
\class Vector2int16
|
||||
A Vector2 that packs its fields into G3D::int16 s.
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(2)
|
||||
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){}
|
||||
explicit Vector2int16(const class Vector2& v);
|
||||
explicit Vector2int16(class BinaryInput& bi);
|
||||
explicit Vector2int16(const class Any& a);
|
||||
explicit Vector2int16(const class Vector2int32& v);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
Vector2int16& operator=(const Any& a);
|
||||
|
||||
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 Vector2int16 operator+(const Vector2int16& other) const {
|
||||
return Vector2int16(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator-(const Vector2int16& other) const {
|
||||
return Vector2int16(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator*(const Vector2int16& other) const {
|
||||
return Vector2int16(x * other.x, y * other.y);
|
||||
}
|
||||
|
||||
Vector2int16 operator-() const {
|
||||
return Vector2int16(-x, -y);
|
||||
}
|
||||
|
||||
inline Vector2int16 operator*(const int s) const {
|
||||
return Vector2int16(x * s, y * s);
|
||||
}
|
||||
|
||||
inline Vector2int16& operator+=(const Vector2int16& other) {
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool isZero() const {
|
||||
return (x == 0) && (y == 0);
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int16 operator>>(const int s) const {
|
||||
return Vector2int16(x >> s, y >> s);
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int16 operator<<(const int s) const {
|
||||
return Vector2int16(x << s, y << s);
|
||||
}
|
||||
|
||||
inline Vector2int16& operator-=(const Vector2int16& other) {
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2int16& operator*=(const Vector2int16& other) {
|
||||
x *= other.x;
|
||||
y *= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2int16 clamp(const Vector2int16& lo, const Vector2int16& hi);
|
||||
|
||||
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];
|
||||
}
|
||||
|
||||
Vector2int16 max(const Vector2int16& v) const {
|
||||
return Vector2int16(iMax(x, v.x), iMax(y, v.y));
|
||||
}
|
||||
|
||||
Vector2int16 min(const Vector2int16& v) const {
|
||||
return Vector2int16(iMin(x, v.x), iMin(y, v.y));
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
}
|
||||
G3D_END_PACKED_CLASS(2)
|
||||
|
||||
typedef Vector2int16 Point2int16;
|
||||
|
||||
}
|
||||
|
||||
template<> struct HashTrait<G3D::Vector2int16> {
|
||||
static size_t hashCode(const G3D::Vector2int16& key) { return static_cast<size_t>(key.x + ((int)key.y << 16)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
134
dep/g3dlite/include/G3D/Vector2int32.h
Normal file
134
dep/g3dlite/include/G3D/Vector2int32.h
Normal file
@@ -0,0 +1,134 @@
|
||||
/**
|
||||
@file G3D/Vector2int32.h
|
||||
|
||||
@maintainer Morgan McGuire, matrix@brown.edu
|
||||
|
||||
@created 2003-08-09
|
||||
@edited 2010-09-03
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Vector2int32_h
|
||||
#define G3D_Vector2int32_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
/**
|
||||
\class Vector2int32
|
||||
A Vector2 that packs its fields into int32s.
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(2)
|
||||
Vector2int32 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector2int32&) const;
|
||||
bool operator>(const Vector2int32&) const;
|
||||
bool operator<=(const Vector2int32&) const;
|
||||
bool operator>=(const Vector2int32&) const;
|
||||
|
||||
public:
|
||||
G3D::int32 x;
|
||||
G3D::int32 y;
|
||||
|
||||
Vector2int32() : x(0), y(0) {}
|
||||
Vector2int32(G3D::int32 _x, G3D::int32 _y) : x(_x), y(_y){}
|
||||
explicit Vector2int32(const class Vector2& v);
|
||||
explicit Vector2int32(class BinaryInput& bi);
|
||||
Vector2int32(const class Vector2int16& v);
|
||||
|
||||
inline G3D::int32& operator[] (int i) {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::int32*)this)[i];
|
||||
}
|
||||
|
||||
inline const G3D::int32& operator[] (int i) const {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::int32*)this)[i];
|
||||
}
|
||||
|
||||
inline Vector2int32 operator+(const Vector2int32& other) const {
|
||||
return Vector2int32(x + other.x, y + other.y);
|
||||
}
|
||||
|
||||
inline Vector2int32 operator-(const Vector2int32& other) const {
|
||||
return Vector2int32(x - other.x, y - other.y);
|
||||
}
|
||||
|
||||
inline Vector2int32 operator-() const {
|
||||
return Vector2int32(-x, -y);
|
||||
}
|
||||
|
||||
inline Vector2int32 operator*(const Vector2int32& other) const {
|
||||
return Vector2int32(x * other.x, y * other.y);
|
||||
}
|
||||
|
||||
inline Vector2int32 operator*(const int s) const {
|
||||
return Vector2int32(x * s, y * s);
|
||||
}
|
||||
|
||||
inline Vector2int32& operator+=(const Vector2int32& other) {
|
||||
x += other.x;
|
||||
y += other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int32 operator>>(const int s) const {
|
||||
return Vector2int32(x >> s, y >> s);
|
||||
}
|
||||
|
||||
/** Shifts both x and y */
|
||||
inline Vector2int32 operator<<(const int s) const {
|
||||
return Vector2int32(x << s, y << s);
|
||||
}
|
||||
|
||||
inline Vector2int32& operator-=(const Vector2int32& other) {
|
||||
x -= other.x;
|
||||
y -= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline Vector2int32& operator*=(const Vector2int32& other) {
|
||||
x *= other.x;
|
||||
y *= other.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2int32 clamp(const Vector2int32& lo, const Vector2int32& hi);
|
||||
|
||||
inline bool operator==(const Vector2int32& other) const {
|
||||
return (x == other.x) && (y == other.y);
|
||||
}
|
||||
|
||||
inline bool operator!= (const Vector2int32& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
Vector2int32 max(const Vector2int32& v) const {
|
||||
return Vector2int32(iMax(x, v.x), iMax(y, v.y));
|
||||
}
|
||||
|
||||
Vector2int32 min(const Vector2int32& v) const {
|
||||
return Vector2int32(iMin(x, v.x), iMin(y, v.y));
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
}
|
||||
G3D_END_PACKED_CLASS(2)
|
||||
|
||||
typedef Vector2int32 Point2int32;
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
template<> struct HashTrait<G3D::Vector2int32> {
|
||||
static size_t hashCode(const G3D::Vector2int32& key) { return static_cast<size_t>(key.x ^ ((int)key.y << 1)); }
|
||||
};
|
||||
|
||||
#endif
|
||||
91
dep/g3dlite/include/G3D/Vector2unorm16.h
Normal file
91
dep/g3dlite/include/G3D/Vector2unorm16.h
Normal file
@@ -0,0 +1,91 @@
|
||||
/**
|
||||
\file G3D/Vector2unorm16.h
|
||||
|
||||
\maintainer Morgan McGuire, morgan@cs.williams.edu
|
||||
|
||||
\created 2003-03-13
|
||||
\edited 2012-03-13
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef Vector2unorm16_h
|
||||
#define Vector2unorm16_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/unorm16.h"
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Any;
|
||||
/**
|
||||
\class Vector2unorm16
|
||||
|
||||
A Vector2 that packs its fields into G3D::unorm16%s. This is mostly
|
||||
useful for texture coordinates that are on the range [0, 1].
|
||||
|
||||
\sa Vector2int16
|
||||
*/
|
||||
G3D_BEGIN_PACKED_CLASS(2)
|
||||
Vector2unorm16 {
|
||||
private:
|
||||
// Hidden operators
|
||||
bool operator<(const Vector2unorm16&) const;
|
||||
bool operator>(const Vector2unorm16&) const;
|
||||
bool operator<=(const Vector2unorm16&) const;
|
||||
bool operator>=(const Vector2unorm16&) const;
|
||||
|
||||
public:
|
||||
G3D::unorm16 x;
|
||||
G3D::unorm16 y;
|
||||
|
||||
Vector2unorm16() {}
|
||||
Vector2unorm16(G3D::unorm16 _x, G3D::unorm16 _y) : x(_x), y(_y){}
|
||||
Vector2unorm16(float _x, float _y) : x(_x), y(_y){}
|
||||
explicit Vector2unorm16(const class Vector2& v);
|
||||
explicit Vector2unorm16(class BinaryInput& bi);
|
||||
explicit Vector2unorm16(const class Any& a);
|
||||
|
||||
Any toAny() const;
|
||||
|
||||
Vector2unorm16& operator=(const Any& a);
|
||||
|
||||
inline G3D::unorm16& operator[] (int i) {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::unorm16*)this)[i];
|
||||
}
|
||||
|
||||
inline const G3D::unorm16& operator[] (int i) const {
|
||||
debugAssert(((unsigned int)i) <= 1);
|
||||
return ((G3D::unorm16*)this)[i];
|
||||
}
|
||||
|
||||
inline bool operator== (const Vector2unorm16& rkVector) const {
|
||||
return ((int32*)this)[0] == ((int32*)&rkVector)[0];
|
||||
}
|
||||
|
||||
inline bool operator!= (const Vector2unorm16& rkVector) const {
|
||||
return ((int32*)this)[0] != ((int32*)&rkVector)[0];
|
||||
}
|
||||
|
||||
void serialize(class BinaryOutput& bo) const;
|
||||
void deserialize(class BinaryInput& bi);
|
||||
size_t hashCode() const {
|
||||
return static_cast<size_t>(x.bits() + ((int)y.bits() << 16));
|
||||
}
|
||||
|
||||
}
|
||||
G3D_END_PACKED_CLASS(2)
|
||||
|
||||
typedef Vector2unorm16 Point2unorm16;
|
||||
|
||||
}
|
||||
|
||||
template<> struct HashTrait<G3D::Vector2unorm16> {
|
||||
static size_t hashCode(const G3D::Vector2unorm16& key) { return key.hashCode(); }
|
||||
};
|
||||
|
||||
#endif
|
||||
845
dep/g3dlite/include/G3D/Vector3.h
Normal file
845
dep/g3dlite/include/G3D/Vector3.h
Normal file
@@ -0,0 +1,845 @@
|
||||
/**
|
||||
\file Vector3.h
|
||||
|
||||
3D vector class
|
||||
|
||||
\maintainer Morgan McGuire, http://graphics.cs.williams.edu
|
||||
|
||||
\created 2001-06-02
|
||||
\edited 2010-12-25
|
||||
|
||||
Copyright 2000-2012, Morgan McGuire.
|
||||
All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef G3D_Vector3_h
|
||||
#define G3D_Vector3_h
|
||||
|
||||
#include "G3D/platform.h"
|
||||
#include "G3D/g3dmath.h"
|
||||
#include "G3D/Random.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include "G3D/Table.h"
|
||||
#include "G3D/HashTrait.h"
|
||||
#include "G3D/PositionTrait.h"
|
||||
#include "G3D/Vector2.h"
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
|
||||
namespace G3D {
|
||||
|
||||
class Vector2;
|
||||
class Vector4;
|
||||
class Vector4int8;
|
||||
class Vector3int32;
|
||||
class Any;
|
||||
|
||||
/**
|
||||
<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 {
|
||||
public:
|
||||
|
||||
// coordinates
|
||||
float x, y, z;
|
||||
|
||||
private:
|
||||
|
||||
// Hidden operators
|
||||
bool operator<(const Vector3&) const;
|
||||
bool operator>(const Vector3&) const;
|
||||
bool operator<=(const Vector3&) const;
|
||||
bool operator>=(const Vector3&) const;
|
||||
|
||||
public:
|
||||
/** Initializes to zero */
|
||||
Vector3();
|
||||
|
||||
/**
|
||||
\param any Must either Vector3(#, #, #) or Vector3 {x = #, y = #, z = #}.
|
||||
Because Point3 is a typedef for Vector3 in the current implementation,
|
||||
this constructor accepts Point3(#, #, #), etc. as well.
|
||||
|
||||
*/
|
||||
explicit Vector3(const Any& any);
|
||||
|
||||
/** Converts the Vector3 to an Any, using the specified \a name instead of "Vector3" */
|
||||
Any toAny(const std::string& name) const;
|
||||
|
||||
/** Converts the Vector3 to an Any. */
|
||||
Any toAny() const;
|
||||
|
||||
/** Divides by 127 */
|
||||
Vector3(const Vector4int8&);
|
||||
Vector3(const class Vector2& v, float z);
|
||||
Vector3(const class Vector3int32& v);
|
||||
explicit Vector3(class BinaryInput& b);
|
||||
Vector3(float _x, float _y, float _z);
|
||||
explicit Vector3(float coordinate[3]);
|
||||
explicit Vector3(double coordinate[3]);
|
||||
Vector3(const class Vector3int16& v);
|
||||
explicit Vector3(class TextInput& t);
|
||||
explicit Vector3(const class Color3& c);
|
||||
|
||||
/** Format is three float32's */
|
||||
void serialize(class BinaryOutput& b) const;
|
||||
void deserialize(class BinaryInput& b);
|
||||
|
||||
/** Format is "(%f, %f, %f)" */
|
||||
void serialize(class TextOutput& t) const;
|
||||
void deserialize(class TextInput& t);
|
||||
|
||||
// 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& __fastcall operator[] (int i) const;
|
||||
float& operator[] (int i);
|
||||
|
||||
bool nonZero() const {
|
||||
return (x != 0) || (y != 0) || (z != 0);
|
||||
}
|
||||
|
||||
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& __fastcall operator= (const Vector3& rkVector);
|
||||
Vector3& operator=(const Any& a);
|
||||
bool operator== (const Vector3& rkVector) const;
|
||||
bool operator!= (const Vector3& rkVector) const;
|
||||
size_t 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;
|
||||
|
||||
/** True if any field is nan */
|
||||
bool isNaN() const;
|
||||
|
||||
/** Returns true if this vector has length ~= 0 */
|
||||
bool isZero() const;
|
||||
|
||||
/** Returns true if this vector has length ~= 1 */
|
||||
bool isUnit() const;
|
||||
|
||||
/** Returns a vector that is \a this translated towards \a goal with a maximum translation of \a maxTranslation. */
|
||||
Vector3 movedTowards(const Vector3& goal, float maxTranslation) const;
|
||||
void moveTowards(const Vector3& goal, float maxTranslation);
|
||||
|
||||
// arithmetic operations
|
||||
Vector3 __fastcall operator+ (const Vector3& v) const;
|
||||
Vector3 __fastcall operator- (const Vector3& v) const;
|
||||
Vector3 __fastcall operator* (float s) const;
|
||||
inline Vector3 __fastcall operator/ (float s) const {
|
||||
return *this * (1.0f / s);
|
||||
}
|
||||
Vector3 __fastcall operator* (const Vector3& v) const;
|
||||
Vector3 __fastcall operator/ (const Vector3& v) const;
|
||||
Vector3 __fastcall operator- () const;
|
||||
|
||||
// arithmetic updates
|
||||
Vector3& __fastcall operator+= (const Vector3& v);
|
||||
Vector3& __fastcall operator-= (const Vector3& v);
|
||||
Vector3& __fastcall operator*= (float s);
|
||||
inline Vector3& __fastcall operator/= (float s) {
|
||||
return (*this *= (1.0f / s));
|
||||
}
|
||||
Vector3& __fastcall operator*= (const Vector3& v);
|
||||
Vector3& __fastcall operator/= (const Vector3& v);
|
||||
|
||||
/** Same as magnitude */
|
||||
float length() const;
|
||||
|
||||
float magnitude() const;
|
||||
|
||||
/** Raise each component of this vector to a power */
|
||||
Vector3 pow(float p) const {
|
||||
return Vector3(powf(x, p), powf(y, p), powf(z, p));
|
||||
}
|
||||
|
||||
/**
|
||||
Returns a unit-length version of this vector.
|
||||
Returns nan if length is almost zero.
|
||||
*/
|
||||
Vector3 direction() const;
|
||||
|
||||
/**
|
||||
Potentially less accurate but faster than direction().
|
||||
Only works if System::hasSSE is true.
|
||||
*/
|
||||
Vector3 fastDirection() const;
|
||||
|
||||
/**
|
||||
Reflect this vector about the (not necessarily unit) normal.
|
||||
Assumes that both the before and after vectors point away from
|
||||
the base of the 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;
|
||||
|
||||
/**
|
||||
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 (mag < 0.0000001f) {
|
||||
return Vector3::zero();
|
||||
} else if (mag < 1.00001f && mag > 0.99999f) {
|
||||
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();
|
||||
}
|
||||
|
||||
/** Same as squaredMagnitude */
|
||||
float squaredLength() const;
|
||||
|
||||
float squaredMagnitude () const;
|
||||
|
||||
float __fastcall dot(const Vector3& rkVector) const;
|
||||
|
||||
/** 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 __fastcall 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 __fastcall min(const Vector3 &v) const;
|
||||
Vector3 __fastcall max(const Vector3 &v) const;
|
||||
|
||||
/** Smallest element */
|
||||
inline float min() const {
|
||||
return G3D::min(G3D::min(x, y), z);
|
||||
}
|
||||
|
||||
/** Largest element */
|
||||
inline float max() const {
|
||||
return G3D::max(G3D::max(x, y), z);
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
inline Vector3 floor() const {
|
||||
return G3D::Vector3(::floor(x), ::floor(y), ::floor(z));
|
||||
}
|
||||
|
||||
|
||||
inline Vector3 round() const {
|
||||
return Vector3(G3D::round(x), G3D::round(y), G3D::round(z));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
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]);
|
||||
|
||||
/** \brief Random unit vector, uniformly distributed on the sphere.
|
||||
|
||||
Distribution rendered by G3D::DirectionHistogram:
|
||||
\image html vector3-random.png
|
||||
*/
|
||||
static Vector3 random(Random& r = Random::common());
|
||||
|
||||
/** \brief Random unit vector, distributed according to \f$\max(\cos \theta,0)\f$.
|
||||
|
||||
That is, so that the probability of \f$\vec{V}\f$ is proportional
|
||||
to \f$\max(\vec{v} \cdot \vec{n}, 0)\f$. Useful in photon mapping for
|
||||
Lambertian scattering.
|
||||
|
||||
Distribution rendered by G3D::DirectionHistogram:
|
||||
\image html vector3-coshemirandom.png
|
||||
|
||||
\param n Unit vector at the center of the distribution.
|
||||
|
||||
@cite Henrik Wann Jensen, Realistic Image Synthesis using Photon Mapping eqn 2.24
|
||||
*/
|
||||
static Vector3 cosHemiRandom(const Vector3& n, Random& r = Random::common());
|
||||
|
||||
static Vector3 cosSphereRandom(const Vector3& n, Random& r = Random::common());
|
||||
|
||||
/** \brief Random unit vector, distributed according to \f$\max(\cos^k \theta,0)\f$.
|
||||
|
||||
That is, so that the probability of \f$\vec{V}\f$ is
|
||||
proportional to \f$\max((\vec{v} \cdot \vec{n})^k, 0)\f$.
|
||||
Useful in photon mapping for glossy scattering.
|
||||
|
||||
Distribution rendered by G3D::DirectionHistogram:
|
||||
\image html vector3-cospowhemirandom.png
|
||||
|
||||
\param n Unit vector at the center of the distribution.
|
||||
|
||||
@cite Ashikhmin and Shirley, An anisotropic Phong BRDF model, Journal of Graphics Tools, 2002
|
||||
*/
|
||||
static Vector3 cosPowHemiRandom(const Vector3& n, const float k, Random& r = Random::common());
|
||||
|
||||
/**
|
||||
\brief Random vector distributed over the hemisphere about normal.
|
||||
|
||||
Distribution rendered by G3D::DirectionHistogram:
|
||||
\image html vector3-hemirandom.png
|
||||
*/
|
||||
static Vector3 hemiRandom(const Vector3& normal, Random& r = Random::common());
|
||||
|
||||
inline float sum() const {
|
||||
return x + y + z;
|
||||
}
|
||||
|
||||
inline float average() const {
|
||||
return sum() / 3.0f;
|
||||
}
|
||||
|
||||
// Special values.
|
||||
static const Vector3& zero();
|
||||
static const Vector3& one();
|
||||
static const Vector3& unitX();
|
||||
static const Vector3& unitY();
|
||||
static const Vector3& unitZ();
|
||||
static const Vector3& inf();
|
||||
static const Vector3& nan();
|
||||
|
||||
/** Smallest (most negative) representable vector */
|
||||
static const Vector3& minFinite();
|
||||
|
||||
/** Largest representable vector */
|
||||
static const Vector3& maxFinite();
|
||||
|
||||
|
||||
/** Creates two orthonormal tangent vectors X and Y such that
|
||||
if Z = this, X x Y = Z.*/
|
||||
inline void getTangents(Vector3& X, Vector3& Y) const {
|
||||
debugAssertM(G3D::fuzzyEq(length(), 1.0f),
|
||||
"makeAxes requires Z to have unit length");
|
||||
|
||||
// Choose another vector not perpendicular
|
||||
X = (abs(x) < 0.9f) ? Vector3::unitX() : Vector3::unitY();
|
||||
|
||||
// Remove the part that is parallel to Z
|
||||
X -= *this * this->dot(X);
|
||||
X /= X.length();
|
||||
|
||||
Y = this->cross(X);
|
||||
}
|
||||
|
||||
|
||||
// 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;
|
||||
|
||||
/** Can be passed to ignore a vector3 parameter */
|
||||
static Vector3& ignore();
|
||||
};
|
||||
|
||||
|
||||
|
||||
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&);
|
||||
|
||||
|
||||
void serialize(const Vector3::Axis& a, class BinaryOutput& bo);
|
||||
void deserialize(Vector3::Axis& a, class BinaryInput& bo);
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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 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 {
|
||||
const float lenSquared = squaredMagnitude();
|
||||
const 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);
|
||||
return kCross.direction();
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
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(fabsf(x) + fabsf(y) + fabsf(z), 0.0f);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
inline bool Vector3::isUnit() const {
|
||||
return G3D::fuzzyEq(squaredMagnitude(), 1.0f);
|
||||
}
|
||||
|
||||
/**
|
||||
Points are technically distinct mathematical entities from vectors.
|
||||
Actually distinguishing them at the class level tends to add lots of
|
||||
boilerplate (e.g., (P - Point3::zero()).direction()
|
||||
vs. P.direction()), so many programmers prefer use a single class,
|
||||
as GLSL does.
|
||||
|
||||
G3D provides this typedef as a way of documenting arguments that are
|
||||
locations in space and not directions. Beware that points and
|
||||
vectors are interchangable from the compiler's point of view, and
|
||||
that the programmer must track which is really which. */
|
||||
typedef Vector3 Point3;
|
||||
|
||||
void serialize(const Vector3& v, class BinaryOutput& b);
|
||||
void deserialize(Vector3& v, class BinaryInput& b);
|
||||
|
||||
} // namespace G3D
|
||||
|
||||
|
||||
template <>
|
||||
struct HashTrait<G3D::Vector3> {
|
||||
static size_t hashCode(const G3D::Vector3& key) {
|
||||
return key.hashCode();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<> struct PositionTrait<class G3D::Vector2> {
|
||||
static void getPosition(const G3D::Vector2& v, G3D::Vector3& p) { p = G3D::Vector3(v, 0); }
|
||||
};
|
||||
|
||||
template<> struct PositionTrait<class G3D::Vector3> {
|
||||
static void getPosition(const G3D::Vector3& v, G3D::Vector3& p) { p = v; }
|
||||
};
|
||||
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user