aboutsummaryrefslogtreecommitdiff
path: root/dep/g3dlite
diff options
context:
space:
mode:
Diffstat (limited to 'dep/g3dlite')
-rw-r--r--dep/g3dlite/CMakeLists.txt4
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix1.diff520
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix2.diff14
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix3.diff12
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix4.diff13
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix5.diff73
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix6.diff103
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix7.diff13
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix8.diff13
-rw-r--r--dep/g3dlite/G3D-v8.0_hotfix9.diff13
-rw-r--r--dep/g3dlite/G3D-v9.0 hotfix1.diff475
-rw-r--r--dep/g3dlite/Readme.txt1
-rw-r--r--dep/g3dlite/include/G3D/AABox.h193
-rw-r--r--dep/g3dlite/include/G3D/Any.h568
-rw-r--r--dep/g3dlite/include/G3D/AnyVal.h512
-rw-r--r--dep/g3dlite/include/G3D/AreaMemoryManager.h12
-rw-r--r--dep/g3dlite/include/G3D/Array.h380
-rw-r--r--dep/g3dlite/include/G3D/AtomicInt32.h10
-rw-r--r--dep/g3dlite/include/G3D/BIN.h92
-rw-r--r--dep/g3dlite/include/G3D/BinaryInput.h128
-rw-r--r--dep/g3dlite/include/G3D/BinaryOutput.h94
-rw-r--r--dep/g3dlite/include/G3D/Box.h158
-rw-r--r--dep/g3dlite/include/G3D/BumpMapPreprocess.h6
-rw-r--r--dep/g3dlite/include/G3D/Capsule.h38
-rw-r--r--dep/g3dlite/include/G3D/CollisionDetection.h1382
-rw-r--r--dep/g3dlite/include/G3D/Color1.h49
-rw-r--r--dep/g3dlite/include/G3D/Color1uint8.h91
-rw-r--r--dep/g3dlite/include/G3D/Color3.h85
-rw-r--r--dep/g3dlite/include/G3D/Color3uint8.h125
-rw-r--r--dep/g3dlite/include/G3D/Color4.h14
-rw-r--r--dep/g3dlite/include/G3D/Color4uint8.h123
-rw-r--r--dep/g3dlite/include/G3D/Cone.h13
-rw-r--r--dep/g3dlite/include/G3D/ConvexPolyhedron.h2
-rw-r--r--dep/g3dlite/include/G3D/CoordinateFrame.h113
-rw-r--r--dep/g3dlite/include/G3D/Crypto.h45
-rw-r--r--dep/g3dlite/include/G3D/Cylinder.h18
-rw-r--r--dep/g3dlite/include/G3D/FileNotFound.h32
-rw-r--r--dep/g3dlite/include/G3D/FileSystem.h369
-rw-r--r--dep/g3dlite/include/G3D/Frustum.h57
-rw-r--r--dep/g3dlite/include/G3D/G3D.h135
-rw-r--r--dep/g3dlite/include/G3D/G3DGameUnits.h9
-rw-r--r--dep/g3dlite/include/G3D/GCamera.h354
-rw-r--r--dep/g3dlite/include/G3D/GImage.h611
-rw-r--r--dep/g3dlite/include/G3D/GLight.h113
-rw-r--r--dep/g3dlite/include/G3D/GMutex.h25
-rw-r--r--dep/g3dlite/include/G3D/GThread.h177
-rw-r--r--dep/g3dlite/include/G3D/GUniqueID.h33
-rw-r--r--dep/g3dlite/include/G3D/HashTrait.h135
-rw-r--r--dep/g3dlite/include/G3D/Image1.h50
-rw-r--r--dep/g3dlite/include/G3D/Image1uint8.h80
-rw-r--r--dep/g3dlite/include/G3D/Image3.h44
-rw-r--r--dep/g3dlite/include/G3D/Image3uint8.h85
-rw-r--r--dep/g3dlite/include/G3D/Image4.h46
-rw-r--r--dep/g3dlite/include/G3D/Image4uint8.h85
-rw-r--r--dep/g3dlite/include/G3D/ImageFormat.h180
-rw-r--r--dep/g3dlite/include/G3D/Intersect.h10
-rw-r--r--dep/g3dlite/include/G3D/KDTree.h197
-rw-r--r--dep/g3dlite/include/G3D/Line.h6
-rw-r--r--dep/g3dlite/include/G3D/LineSegment.h50
-rw-r--r--dep/g3dlite/include/G3D/Log.h2
-rw-r--r--dep/g3dlite/include/G3D/Map2D.h85
-rw-r--r--dep/g3dlite/include/G3D/Matrix.h13
-rw-r--r--dep/g3dlite/include/G3D/Matrix2.h20
-rw-r--r--dep/g3dlite/include/G3D/Matrix3.h63
-rw-r--r--dep/g3dlite/include/G3D/Matrix4.h142
-rw-r--r--dep/g3dlite/include/G3D/MemoryManager.h11
-rw-r--r--dep/g3dlite/include/G3D/MeshAlg.h21
-rw-r--r--dep/g3dlite/include/G3D/MeshBuilder.h6
-rw-r--r--dep/g3dlite/include/G3D/NetAddress.h36
-rw-r--r--dep/g3dlite/include/G3D/NetworkDevice.h36
-rw-r--r--dep/g3dlite/include/G3D/ParseError.h3
-rw-r--r--dep/g3dlite/include/G3D/PhysicsFrame.h35
-rw-r--r--dep/g3dlite/include/G3D/PhysicsFrameSpline.h19
-rw-r--r--dep/g3dlite/include/G3D/Plane.h68
-rw-r--r--dep/g3dlite/include/G3D/PointHashGrid.h242
-rw-r--r--dep/g3dlite/include/G3D/PointKDTree.h155
-rw-r--r--dep/g3dlite/include/G3D/Pointer.h128
-rw-r--r--dep/g3dlite/include/G3D/Quat.h105
-rw-r--r--dep/g3dlite/include/G3D/Queue.h12
-rw-r--r--dep/g3dlite/include/G3D/Random.h37
-rw-r--r--dep/g3dlite/include/G3D/Ray.h191
-rw-r--r--dep/g3dlite/include/G3D/Rect2D.h139
-rw-r--r--dep/g3dlite/include/G3D/ReferenceCount.h568
-rw-r--r--dep/g3dlite/include/G3D/RegistryUtil.h4
-rw-r--r--dep/g3dlite/include/G3D/Set.h7
-rw-r--r--dep/g3dlite/include/G3D/SmallArray.h53
-rw-r--r--dep/g3dlite/include/G3D/SpawnBehavior.h6
-rw-r--r--dep/g3dlite/include/G3D/Sphere.h58
-rw-r--r--dep/g3dlite/include/G3D/Spline.h124
-rw-r--r--dep/g3dlite/include/G3D/SplineExtrapolationMode.h94
-rw-r--r--dep/g3dlite/include/G3D/Stopwatch.h17
-rw-r--r--dep/g3dlite/include/G3D/System.h185
-rw-r--r--dep/g3dlite/include/G3D/Table.h189
-rw-r--r--dep/g3dlite/include/G3D/TextInput.h77
-rw-r--r--dep/g3dlite/include/G3D/TextOutput.h29
-rw-r--r--dep/g3dlite/include/G3D/ThreadSet.h25
-rw-r--r--dep/g3dlite/include/G3D/Triangle.h32
-rw-r--r--dep/g3dlite/include/G3D/UprightFrame.h68
-rw-r--r--dep/g3dlite/include/G3D/Vector2.h96
-rw-r--r--dep/g3dlite/include/G3D/Vector2int16.h33
-rw-r--r--dep/g3dlite/include/G3D/Vector2int32.h134
-rw-r--r--dep/g3dlite/include/G3D/Vector2unorm16.h91
-rw-r--r--dep/g3dlite/include/G3D/Vector3.h103
-rw-r--r--dep/g3dlite/include/G3D/Vector3int16.h67
-rw-r--r--dep/g3dlite/include/G3D/Vector3int32.h97
-rw-r--r--dep/g3dlite/include/G3D/Vector4.h11
-rw-r--r--dep/g3dlite/include/G3D/Vector4int8.h6
-rw-r--r--dep/g3dlite/include/G3D/WeakCache.h65
-rw-r--r--dep/g3dlite/include/G3D/Welder.h26
-rw-r--r--dep/g3dlite/include/G3D/WrapMode.h20
-rw-r--r--dep/g3dlite/include/G3D/XML.h10
-rw-r--r--dep/g3dlite/include/G3D/constants.h37
-rw-r--r--dep/g3dlite/include/G3D/debug.h22
-rw-r--r--dep/g3dlite/include/G3D/enumclass.h180
-rw-r--r--dep/g3dlite/include/G3D/fileutils.h44
-rw-r--r--dep/g3dlite/include/G3D/g3dfnmatch.h2
-rw-r--r--dep/g3dlite/include/G3D/g3dmath.h273
-rw-r--r--dep/g3dlite/include/G3D/netheaders.h2
-rw-r--r--dep/g3dlite/include/G3D/networkHelpers.h2
-rw-r--r--dep/g3dlite/include/G3D/platform.h218
-rw-r--r--dep/g3dlite/include/G3D/serialize.h62
-rw-r--r--dep/g3dlite/include/G3D/stringutils.h66
-rw-r--r--dep/g3dlite/include/G3D/uint128.h35
-rw-r--r--dep/g3dlite/include/G3D/units.h40
-rw-r--r--dep/g3dlite/include/G3D/unorm16.h180
-rw-r--r--dep/g3dlite/include/G3D/unorm8.h177
-rw-r--r--dep/g3dlite/source/AABox.cpp157
-rw-r--r--dep/g3dlite/source/Any.cpp783
-rw-r--r--dep/g3dlite/source/AnyTableReader.cpp50
-rw-r--r--dep/g3dlite/source/AnyVal.cpp1379
-rw-r--r--dep/g3dlite/source/AreaMemoryManager.cpp4
-rw-r--r--dep/g3dlite/source/BinaryInput.cpp503
-rw-r--r--dep/g3dlite/source/BinaryOutput.cpp109
-rw-r--r--dep/g3dlite/source/Box.cpp394
-rw-r--r--dep/g3dlite/source/BumpMapPreprocess.cpp6
-rw-r--r--dep/g3dlite/source/Capsule.cpp44
-rw-r--r--dep/g3dlite/source/CollisionDetection.cpp389
-rw-r--r--dep/g3dlite/source/Color1.cpp14
-rw-r--r--dep/g3dlite/source/Color1uint8.cpp38
-rw-r--r--dep/g3dlite/source/Color3.cpp164
-rw-r--r--dep/g3dlite/source/Color3uint8.cpp45
-rw-r--r--dep/g3dlite/source/Color4.cpp71
-rw-r--r--dep/g3dlite/source/Color4uint8.cpp47
-rw-r--r--dep/g3dlite/source/Cone.cpp54
-rw-r--r--dep/g3dlite/source/ConvexPolyhedron.cpp32
-rw-r--r--dep/g3dlite/source/CoordinateFrame.cpp168
-rw-r--r--dep/g3dlite/source/Crypto.cpp5
-rw-r--r--dep/g3dlite/source/Crypto_md5.cpp134
-rw-r--r--dep/g3dlite/source/Cylinder.cpp30
-rw-r--r--dep/g3dlite/source/FileSystem.cpp369
-rw-r--r--dep/g3dlite/source/GCamera.cpp511
-rw-r--r--dep/g3dlite/source/GImage.cpp1166
-rw-r--r--dep/g3dlite/source/GImage_bayer.cpp298
-rw-r--r--dep/g3dlite/source/GImage_bmp.cpp717
-rw-r--r--dep/g3dlite/source/GImage_jpeg.cpp446
-rw-r--r--dep/g3dlite/source/GImage_png.cpp276
-rw-r--r--dep/g3dlite/source/GImage_ppm.cpp217
-rw-r--r--dep/g3dlite/source/GImage_tga.cpp236
-rw-r--r--dep/g3dlite/source/GLight.cpp275
-rw-r--r--dep/g3dlite/source/GThread.cpp61
-rw-r--r--dep/g3dlite/source/GUniqueID.cpp46
-rw-r--r--dep/g3dlite/source/Image1.cpp123
-rw-r--r--dep/g3dlite/source/Image1uint8.cpp212
-rw-r--r--dep/g3dlite/source/Image3.cpp116
-rw-r--r--dep/g3dlite/source/Image3uint8.cpp225
-rw-r--r--dep/g3dlite/source/Image4.cpp114
-rw-r--r--dep/g3dlite/source/Image4uint8.cpp222
-rw-r--r--dep/g3dlite/source/ImageFormat.cpp494
-rw-r--r--dep/g3dlite/source/ImageFormat_convert.cpp682
-rw-r--r--dep/g3dlite/source/Intersect.cpp1533
-rw-r--r--dep/g3dlite/source/Line.cpp12
-rw-r--r--dep/g3dlite/source/LineSegment.cpp10
-rw-r--r--dep/g3dlite/source/Log.cpp16
-rw-r--r--dep/g3dlite/source/Matrix.cpp125
-rw-r--r--dep/g3dlite/source/Matrix3.cpp363
-rw-r--r--dep/g3dlite/source/Matrix4.cpp291
-rw-r--r--dep/g3dlite/source/MemoryManager.cpp6
-rw-r--r--dep/g3dlite/source/MeshAlg.cpp98
-rw-r--r--dep/g3dlite/source/MeshAlgAdjacency.cpp11
-rw-r--r--dep/g3dlite/source/MeshAlgWeld.cpp27
-rw-r--r--dep/g3dlite/source/MeshBuilder.cpp26
-rw-r--r--dep/g3dlite/source/NetAddress.cpp45
-rw-r--r--dep/g3dlite/source/NetworkDevice.cpp99
-rw-r--r--dep/g3dlite/source/PhysicsFrame.cpp40
-rw-r--r--dep/g3dlite/source/PhysicsFrameSpline.cpp77
-rw-r--r--dep/g3dlite/source/Plane.cpp38
-rw-r--r--dep/g3dlite/source/Quat.cpp122
-rw-r--r--dep/g3dlite/source/Random.cpp30
-rw-r--r--dep/g3dlite/source/Ray.cpp221
-rw-r--r--dep/g3dlite/source/Rect2D.cpp46
-rw-r--r--dep/g3dlite/source/ReferenceCount.cpp61
-rw-r--r--dep/g3dlite/source/RegistryUtil.cpp8
-rw-r--r--dep/g3dlite/source/Sphere.cpp122
-rw-r--r--dep/g3dlite/source/SplineBase.cpp6
-rw-r--r--dep/g3dlite/source/Stopwatch.cpp15
-rw-r--r--dep/g3dlite/source/System.cpp526
-rw-r--r--dep/g3dlite/source/TextInput.cpp310
-rw-r--r--dep/g3dlite/source/TextOutput.cpp79
-rw-r--r--dep/g3dlite/source/ThreadSet.cpp14
-rw-r--r--dep/g3dlite/source/Triangle.cpp2
-rw-r--r--dep/g3dlite/source/UprightFrame.cpp112
-rw-r--r--dep/g3dlite/source/Vector2.cpp57
-rw-r--r--dep/g3dlite/source/Vector2int16.cpp40
-rw-r--r--dep/g3dlite/source/Vector3.cpp146
-rw-r--r--dep/g3dlite/source/Vector3int16.cpp10
-rw-r--r--dep/g3dlite/source/Vector3int32.cpp83
-rw-r--r--dep/g3dlite/source/Vector4.cpp24
-rw-r--r--dep/g3dlite/source/Welder.cpp276
-rw-r--r--dep/g3dlite/source/WinMain.cpp2
-rw-r--r--dep/g3dlite/source/XML.cpp4
-rw-r--r--dep/g3dlite/source/constants.cpp28
-rw-r--r--dep/g3dlite/source/debugAssert.cpp30
-rw-r--r--dep/g3dlite/source/fileutils.cpp314
-rw-r--r--dep/g3dlite/source/format.cpp12
-rw-r--r--dep/g3dlite/source/g3dfnmatch.cpp306
-rw-r--r--dep/g3dlite/source/g3dmath.cpp24
-rw-r--r--dep/g3dlite/source/license.cpp4
-rw-r--r--dep/g3dlite/source/prompt.cpp179
-rw-r--r--dep/g3dlite/source/stringutils.cpp68
-rw-r--r--dep/g3dlite/source/uint128.cpp8
220 files changed, 13724 insertions, 17400 deletions
diff --git a/dep/g3dlite/CMakeLists.txt b/dep/g3dlite/CMakeLists.txt
index 7013e051535..1914e66f7c4 100644
--- a/dep/g3dlite/CMakeLists.txt
+++ b/dep/g3dlite/CMakeLists.txt
@@ -12,6 +12,7 @@
set(g3dlib_STAT_SRCS
source/AABox.cpp
source/Any.cpp
+ source/AnyTableReader.cpp
source/BinaryFormat.cpp
source/BinaryInput.cpp
source/BinaryOutput.cpp
@@ -27,6 +28,7 @@ set(g3dlib_STAT_SRCS
source/format.cpp
source/g3dfnmatch.cpp
source/g3dmath.cpp
+ source/GThread.cpp
source/Line.cpp
source/LineSegment.cpp
source/Log.cpp
@@ -39,7 +41,6 @@ set(g3dlib_STAT_SRCS
source/Quat.cpp
source/Random.cpp
source/Ray.cpp
- source/ReferenceCount.cpp
source/RegistryUtil.cpp
source/Sphere.cpp
source/stringutils.cpp
@@ -69,4 +70,5 @@ add_library(g3dlib STATIC ${g3dlib_STAT_SRCS})
target_link_libraries(g3dlib
${ZLIB_LIBRARIES}
+ ${CMAKE_THREAD_LIBS_INIT}
)
diff --git a/dep/g3dlite/G3D-v8.0_hotfix1.diff b/dep/g3dlite/G3D-v8.0_hotfix1.diff
deleted file mode 100644
index ec90cebbecf..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix1.diff
+++ /dev/null
@@ -1,520 +0,0 @@
-diff -urN a/dep/g3dlite/include/G3D/debugAssert.h b/dep/g3dlite/include/G3D/debugAssert.h
---- a/dep/g3dlite/include/G3D/debugAssert.h 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/include/G3D/debugAssert.h 2010-08-26 21:36:32.000000000 +0200
-@@ -39,10 +39,12 @@
- #ifdef G3D_LINUX
- // Needed so we can define a global display
- // pointer for debugAssert.
-+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
- #include <X11/Xlib.h>
- #include <X11/Xutil.h>
- #include <X11/Xatom.h>
- #endif
-+#endif
-
-
- /**
-@@ -178,6 +180,7 @@
- namespace G3D { namespace _internal {
-
- #ifdef G3D_LINUX
-+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
- /**
- A pointer to the X11 display. Initially NULL. If set to a
- non-null value (e.g. by SDLWindow), debugAssert attempts to use
-@@ -194,6 +197,7 @@
- */
- extern Window x11Window;
- #endif
-+#endif
-
- /**
- Pops up an assertion dialog or prints an assertion
-diff -urN a/dep/g3dlite/include/G3D/g3dmath.h b/dep/g3dlite/include/G3D/g3dmath.h
---- a/dep/g3dlite/include/G3D/g3dmath.h 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/include/G3D/g3dmath.h 2010-08-26 21:36:32.000000000 +0200
-@@ -65,6 +65,8 @@
- return ::rand() / double(RAND_MAX);
- }
-
-+#if !defined(_WIN64)
-+
- /**
- Win32 implementation of the C99 fast rounding routines.
-
-@@ -99,6 +101,19 @@
-
- return intgr;
- }
-+
-+#else
-+
-+ __inline long int lrint (double flt) {
-+ return (long int)floor(flt+0.5f);
-+ }
-+
-+ __inline long int lrintf(float flt) {
-+ return (long int)floorf(flt+0.5f);
-+ }
-+
-+#endif
-+
- #endif
-
-
-diff -urN a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h
---- a/dep/g3dlite/include/G3D/platform.h 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/include/G3D/platform.h 2010-08-26 21:36:32.000000000 +0200
-@@ -56,12 +57,15 @@
- // pi as a constant, which creates a conflict with G3D
- #define __FP__
- #else
-- #error Unknown platform
-+ #error Unknown platform
- #endif
-
- // Detect 64-bit under various compilers
- #if (defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64))
- # define G3D_64BIT
-+ #if defined(WIN32)
-+ #include <intrin.h>
-+ #endif
- #else
- # define G3D_32BIT
- #endif
-@@ -126,13 +130,11 @@
- // TODO: remove
- # pragma warning (disable : 4244)
-
--# define ZLIB_WINAPI
--
- # define restrict
-
- /** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
--# define G3D_CHECK_PRINTF_ARGS
-+# define G3D_CHECK_PRINTF_ARGS
-
- /** @def G3D_CHECK_PRINTF_METHOD_ARGS()
- Enables printf parameter validation on gcc. */
-diff -urN a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h
---- a/dep/g3dlite/include/G3D/System.h 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/include/G3D/System.h 2010-08-26 21:36:32.000000000 +0200
-@@ -375,10 +375,10 @@
- // count now contains the cycle count for the intervening operation.
- </PRE>
- */
-- static void beginCycleCount(uint64& cycleCount);
-+ /* static void beginCycleCount(uint64& cycleCount);
- static void endCycleCount(uint64& cycleCount);
-
-- static uint64 getCycleCount();
-+ static uint64 getCycleCount(); */
-
- inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) {
- instance().m_outOfMemoryCallback = c;
-@@ -438,7 +438,7 @@
-
- };
-
--
-+/* don't need that for MaNGOS, not portable to Win64...
- #ifdef _MSC_VER
- inline uint64 System::getCycleCount() {
- uint32 timehi, timelo;
-@@ -493,14 +493,14 @@
- cycleCount = getCycleCount() - cycleCount;
- #else
- AbsoluteTime end = UpTime();
-- Nanoseconds diffNS =
-+ Nanoseconds diffNS =
- AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
-- cycleCount =
-- (uint64) ((double) (instance().m_OSXCPUSpeed) *
-+ cycleCount =
-+ (uint64) ((double) (instance().m_OSXCPUSpeed) *
- (double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS);
- #endif
- }
--
-+ */
-
- } // namespace
-
-diff -urN a/dep/g3dlite/source/BinaryInput.cpp b/dep/g3dlite/source/BinaryInput.cpp
---- a/dep/g3dlite/source/BinaryInput.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/BinaryInput.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -39,7 +39,9 @@
- #include "G3D/Log.h"
- #include "G3D/FileSystem.h"
- #include <zlib.h>
--#include "zip.h"
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
-+ #include "zip.h"
-+#endif
- #include <cstring>
-
- namespace G3D {
-@@ -273,6 +275,7 @@ BinaryInput::BinaryInput(
- _internal::currentFilesUsed.insert(m_filename);
-
-
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- std::string zipfile;
- if (FileSystem::inZipfile(m_filename, zipfile)) {
- // Load from zipfile
-@@ -304,6 +307,7 @@ BinaryInput::BinaryInput(
- m_freeBuffer = true;
- return;
- }
-+#endif
-
- // Figure out how big the file is and verify that it exists.
- m_length = FileSystem::size(m_filename);
-diff -urN a/dep/g3dlite/source/debugAssert.cpp b/dep/g3dlite/source/debugAssert.cpp
---- a/dep/g3dlite/source/debugAssert.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/debugAssert.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -37,9 +37,11 @@
- AssertionHook _failureHook = _handleErrorCheck_;
-
- #ifdef G3D_LINUX
-+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
- Display* x11Display = NULL;
- Window x11Window = 0;
- #endif
-+#endif
-
-
- #ifdef G3D_WIN32
-@@ -250,6 +252,7 @@
- ClipCursor(NULL);
-
- #elif defined(G3D_LINUX)
-+#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
- if (x11Display != NULL) {
- XUngrabPointer(x11Display, CurrentTime);
- XUngrabKeyboard(x11Display, CurrentTime);
-@@ -264,6 +267,7 @@
- XAllowEvents(x11Display, AsyncPointer, CurrentTime);
- XFlush(x11Display);
- }
-+#endif
- #elif defined(G3D_OSX)
- // TODO: OS X
- #endif
-diff -urN a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp
---- a/dep/g3dlite/source/FileSystem.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/FileSystem.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -12,7 +12,9 @@
- #include "G3D/fileutils.h"
- #include <sys/stat.h>
- #include <sys/types.h>
--#include "zip.h"
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
-+ #include "zip.h"
-+#endif
- #include "G3D/g3dfnmatch.h"
- #include "G3D/BinaryInput.h"
- #include "G3D/BinaryOutput.h"
-@@ -78,6 +80,7 @@ bool FileSystem::Dir::contains(const std
- }
-
- void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile) {
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
- debugAssert(z);
-
-@@ -126,6 +129,7 @@ void FileSystem::Dir::computeZipListing(
-
- zip_close(z);
- z = NULL;
-+#endif
- }
-
-
-@@ -522,6 +526,7 @@ int64 FileSystem::_size(const std::strin
- int result = stat64(filename.c_str(), &st);
-
- if (result == -1) {
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- std::string zip, contents;
- if (zipfileExists(filename, zip, contents)) {
- int64 requiredMem;
-@@ -538,8 +543,11 @@ int64 FileSystem::_size(const std::strin
- zip_close(z);
- return requiredMem;
- } else {
-+#endif
- return -1;
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- }
-+#endif
- }
-
- return st.st_size;
-diff -urN a/dep/g3dlite/source/fileutils.cpp b/dep/g3dlite/source/fileutils.cpp
---- a/dep/g3dlite/source/fileutils.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/fileutils.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -20,7 +20,9 @@
-
- #include <sys/stat.h>
- #include <sys/types.h>
--#include "zip.h"
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
-+ #include "zip.h"
-+#endif
-
- #ifdef G3D_WIN32
- // Needed for _getcwd
-@@ -144,7 +146,7 @@
- void*& data,
- size_t& length) {
- std::string zip, desiredFile;
--
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- if (zipfileExists(file, zip, desiredFile)) {
- struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
- {
-@@ -167,6 +169,9 @@
- } else {
- data = NULL;
- }
-+#else
-+ data = NULL;
-+#endif
- }
-
-
-@@ -180,6 +185,7 @@
- int result = _stat(filename.c_str(), &st);
-
- if (result == -1) {
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- std::string zip, contents;
- if(zipfileExists(filename, zip, contents)){
- int64 requiredMem;
-@@ -198,6 +204,9 @@
- } else {
- return -1;
- }
-+#else
-+ return -1;
-+#endif
- }
-
- return st.st_size;
-@@ -518,6 +527,7 @@
-
- ///////////////////////////////////////////////////////////////////////////////
-
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- /* Helper methods for zipfileExists()*/
- // Given a string (the drive) and an array (the path), computes the directory
- static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
-@@ -551,12 +561,12 @@
- }
- return true;
- }
--
-+#endif
-
- // If no zipfile exists, outZipfile and outInternalFile are unchanged
- bool zipfileExists(const std::string& filename, std::string& outZipfile,
- std::string& outInternalFile){
--
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- Array<std::string> path;
- std::string drive, base, ext, zipfile, infile;
- parseFilename(filename, drive, path, base, ext);
-@@ -618,7 +628,7 @@
- }
-
- }
--
-+#endif
- // not a valid directory structure ever,
- // obviously no .zip was found within the path
- return false;
-@@ -900,7 +910,7 @@
- # endif
- }
-
--
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- /**
- @param path The zipfile name (no trailing slash)
- @param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty.
-@@ -951,13 +961,14 @@
- }
- }
- }
--
-+#endif
-
- static void getFileOrDirListZip(const std::string& path,
- const std::string& prefix,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath){
-+#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL );
-
- Set<std::string> fileSet;
-@@ -973,6 +984,7 @@
- zip_close( z );
-
- fileSet.getMembers(files);
-+#endif
- }
-
-
-diff -urN a/dep/g3dlite/source/prompt.cpp b/dep/g3dlite/source/prompt.cpp
---- a/dep/g3dlite/source/prompt.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/prompt.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -21,6 +21,7 @@
- # define _getch getchar
- #endif
-
-+#if 0 /* G3DFIX: exclude GUI prompt code */
- #ifdef G3D_OSX
-
- /*#ifdef __LP64__
-@@ -37,9 +38,11 @@
- */
-
- #endif
-+#endif /* G3DFIX: exclude GUI prompt code */
-
- namespace G3D {
-
-+#if 0 /* G3DFIX: exclude GUI prompt code */
- #ifdef G3D_WIN32
-
- namespace _internal {
-@@ -469,6 +472,7 @@
- }
-
- #endif
-+#endif /* G3DFIX: exclude GUI prompt code */
-
-
- /**
-@@ -531,6 +535,8 @@
- return c;
- }
-
-+#if 0 /* G3DFIX: exclude GUI prompt code */
-+
- #ifdef G3D_OSX
-
- // See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html
-@@ -689,13 +695,15 @@
-
- #endif
-
-+#endif /* G3DFIX: exclude GUI prompt code */
-+
- int prompt(
- const char* windowTitle,
- const char* prompt,
- const char** choice,
- int numChoices,
- bool useGui) {
--
-+#if 0 /* G3DFIX: exclude GUI prompt code */
- #ifdef G3D_WIN32
- if (useGui) {
- // Build the message box
-@@ -709,6 +717,7 @@
- return guiPrompt(windowTitle, prompt, choice, numChoices);
- }
- #endif
-+#endif /* G3DFIX: exclude GUI prompt code */
- return textPrompt(windowTitle, prompt, choice, numChoices);
- }
-
-diff -urN a/dep/g3dlite/source/RegistryUtil.cpp b/dep/g3dlite/source/RegistryUtil.cpp
---- a/dep/g3dlite/source/RegistryUtil.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/RegistryUtil.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -257,7 +257,7 @@
-
-
- // static helpers
--static HKEY getRootKeyFromString(const char* str, uint32 length) {
-+static HKEY getRootKeyFromString(const char* str, size_t length) {
- debugAssert(str);
-
- if (str) {
-diff -urN a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp
---- a/dep/g3dlite/source/System.cpp 2010-02-07 23:39:20.000000000 +0100
-+++ b/dep/g3dlite/source/System.cpp 2010-08-15 11:37:26.000000000 +0200
-@@ -80,8 +80,9 @@
- #endif
-
- // SIMM include
-+#ifdef __SSE__
- #include <xmmintrin.h>
--
-+#endif
-
- namespace G3D {
-
-@@ -559,7 +560,7 @@
- #endif
- }
-
--#if defined(G3D_WIN32)
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
- #pragma message("Port System::memcpy SIMD to all platforms")
- /** Michael Herf's fast memcpy */
- void memcpyMMX(void* dst, const void* src, int nbytes) {
-@@ -610,7 +611,7 @@
- #endif
-
- void System::memcpy(void* dst, const void* src, size_t numBytes) {
--#if defined(G3D_WIN32)
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
- memcpyMMX(dst, src, numBytes);
- #else
- ::memcpy(dst, src, numBytes);
-@@ -620,7 +621,7 @@
-
- /** Michael Herf's fastest memset. n32 must be filled with the same
- character repeated. */
--#if defined(G3D_WIN32)
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
- #pragma message("Port System::memfill SIMD to all platforms")
-
- // On x86 processors, use MMX
-@@ -659,7 +660,7 @@
-
-
- void System::memset(void* dst, uint8 value, size_t numBytes) {
--#if defined(G3D_WIN32)
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
- uint32 v = value;
- v = v + (v << 8) + (v << 16) + (v << 24);
- G3D::memfill(dst, v, numBytes);
-@@ -1676,6 +1677,7 @@
-
- // VC on Intel
- void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
-+#if !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit platform */
- // Can't copy from assembler direct to a function argument (which is on the stack) in VC.
- uint32 a,b,c,d;
-
-@@ -1693,6 +1695,14 @@
- breg = b;
- creg = c;
- dreg = d;
-+#else
-+ int CPUInfo[4];
-+ __cpuid(CPUInfo, func);
-+ memcpy(&areg, &CPUInfo[0], 4);
-+ memcpy(&breg, &CPUInfo[1], 4);
-+ memcpy(&creg, &CPUInfo[2], 4);
-+ memcpy(&dreg, &CPUInfo[3], 4);
-+#endif
- }
-
- #elif defined(G3D_OSX) && ! defined(G3D_OSX_INTEL)
diff --git a/dep/g3dlite/G3D-v8.0_hotfix2.diff b/dep/g3dlite/G3D-v8.0_hotfix2.diff
deleted file mode 100644
index bb66c4a6a29..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix2.diff
+++ /dev/null
@@ -1,14 +0,0 @@
-diff --git a/dep/g3dlite/source/g3dmath.cpp b/dep/g3dlite/source/g3dmath.cpp
-index e846f8c..84e8345 100644
---- a/dep/g3dlite/source/g3dmath.cpp
-+++ b/dep/g3dlite/source/g3dmath.cpp
-@@ -41,7 +41,7 @@ double inf() {
- }
-
- bool isNaN(float x) {
-- static const float n = nan();
-+ static const float n = fnan();
- return memcmp(&x, &n, sizeof(float)) == 0;
- }
-
-
diff --git a/dep/g3dlite/G3D-v8.0_hotfix3.diff b/dep/g3dlite/G3D-v8.0_hotfix3.diff
deleted file mode 100644
index d556103c96d..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix3.diff
+++ /dev/null
@@ -1,12 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/GMutex.h b/dep/g3dlite/include/G3D/GMutex.h
-index 3469b81..9fe098d 100644
---- a/dep/g3dlite/include/G3D/GMutex.h
-+++ b/dep/g3dlite/include/G3D/GMutex.h
-@@ -16,6 +16,7 @@
- #ifndef G3D_WIN32
- # include <pthread.h>
- # include <signal.h>
-+# include <unistd.h>
- #endif
-
-
diff --git a/dep/g3dlite/G3D-v8.0_hotfix4.diff b/dep/g3dlite/G3D-v8.0_hotfix4.diff
deleted file mode 100644
index cae92747a9a..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix4.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h
-index c8d2f0b..11093f4 100644
---- a/dep/g3dlite/include/G3D/platform.h
-+++ b/dep/g3dlite/include/G3D/platform.h
-@@ -57,7 +57,7 @@
- #elif defined(__linux__)
- #define G3D_LINUX
- #elif defined(__APPLE__)
-- #define G3D_OSX
-+ #define G3D_LINUX
-
- // Prevent OS X fp.h header from being included; it defines
- // pi as a constant, which creates a conflict with G3D
diff --git a/dep/g3dlite/G3D-v8.0_hotfix5.diff b/dep/g3dlite/G3D-v8.0_hotfix5.diff
deleted file mode 100644
index fd02b329c4a..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix5.diff
+++ /dev/null
@@ -1,73 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h
-index 1c0cf99..f160774 100644
---- a/dep/g3dlite/include/G3D/System.h
-+++ b/dep/g3dlite/include/G3D/System.h
-@@ -19,6 +19,9 @@
- #include "G3D/G3DGameUnits.h"
- #include "G3D/BinaryFormat.h"
- #include <string>
-+#ifdef G3D_LINUX
-+# include <sys/socket.h>
-+#endif
-
- #ifdef G3D_OSX
- # include <CoreServices/CoreServices.h>
-diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h
-index 11093f4..614c0ed 100644
---- a/dep/g3dlite/include/G3D/platform.h
-+++ b/dep/g3dlite/include/G3D/platform.h
-@@ -56,6 +56,8 @@
- #define G3D_LINUX
- #elif defined(__linux__)
- #define G3D_LINUX
-+#elif defined(__CYGWIN__)
-+ #define G3D_LINUX
- #elif defined(__APPLE__)
- #define G3D_LINUX
-
-diff --git a/dep/g3dlite/source/BinaryOutput.cpp b/dep/g3dlite/source/BinaryOutput.cpp
-index 054211d..81fa982 100644
---- a/dep/g3dlite/source/BinaryOutput.cpp
-+++ b/dep/g3dlite/source/BinaryOutput.cpp
-@@ -22,6 +22,10 @@
- # include <errno.h>
- #endif
-
-+#ifdef __CYGWIN__
-+# include <errno.h>
-+#endif
-+
- // Largest memory buffer that the system will use for writing to
- // disk. After this (or if the system runs out of memory)
- // chunks of the file will be dumped to disk.
-diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp
-index 2cf890a..76a3611 100644
---- a/dep/g3dlite/source/FileSystem.cpp
-+++ b/dep/g3dlite/source/FileSystem.cpp
-@@ -35,6 +35,10 @@
- # define _stat stat
- #endif
-
-+#ifdef __CYGWIN__
-+#define stat64 stat
-+#endif
-+
- namespace G3D {
-
- static FileSystem* common = NULL;
-diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp
-index 809f05c..f6b0e03 100644
---- a/dep/g3dlite/source/System.cpp
-+++ b/dep/g3dlite/source/System.cpp
-@@ -888,7 +888,11 @@ void System::initTime() {
-
- if (localTimeVals) {
- // tm_gmtoff is already corrected for daylight savings.
-+ #ifdef __CYGWIN__
-+ local = local + _timezone;
-+ #else
- local = local + localTimeVals->tm_gmtoff;
-+ #endif
- }
-
- m_realWorldGetTickTime0 = local;
diff --git a/dep/g3dlite/G3D-v8.0_hotfix6.diff b/dep/g3dlite/G3D-v8.0_hotfix6.diff
deleted file mode 100644
index f22c26d4a7e..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix6.diff
+++ /dev/null
@@ -1,103 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h
-index 614c0ed..65616f0 100644
---- a/dep/g3dlite/include/G3D/platform.h
-+++ b/dep/g3dlite/include/G3D/platform.h
-@@ -51,6 +51,11 @@
-
- #ifdef _MSC_VER
- #define G3D_WIN32
-+#elif defined(__MINGW32__)
-+ #define G3D_WIN32
-+ #undef __MSVCRT_VERSION__
-+ #define __MSVCRT_VERSION__ 0x0601
-+ #include <windows.h>
- #elif defined(__FreeBSD__) || defined(__OpenBSD__)
- #define G3D_FREEBSD
- #define G3D_LINUX
-diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp
-index 76a3611..f082937 100644
---- a/dep/g3dlite/source/FileSystem.cpp
-+++ b/dep/g3dlite/source/FileSystem.cpp
-@@ -25,8 +25,11 @@
-
- // Needed for _findfirst
- # include <io.h>
--
--#define stat64 _stat64
-+# ifdef __MINGW32__
-+# define stat64 stat
-+# else
-+# define stat64 _stat64
-+# endif
- #else
- # include <dirent.h>
- # include <fnmatch.h>
-diff --git a/dep/g3dlite/source/RegistryUtil.cpp b/dep/g3dlite/source/RegistryUtil.cpp
-index fc4cebc..7c9e56f 100644
---- a/dep/g3dlite/source/RegistryUtil.cpp
-+++ b/dep/g3dlite/source/RegistryUtil.cpp
-@@ -16,6 +16,15 @@
- #include "G3D/RegistryUtil.h"
- #include "G3D/System.h"
-
-+#ifdef __MINGW32__
-+# ifndef HKEY_PERFORMANCE_TEXT
-+# define HKEY_PERFORMANCE_TEXT ((HKEY)((LONG)0x80000050))
-+# endif
-+# ifndef HKEY_PERFORMANCE_NLSTEXT
-+# define HKEY_PERFORMANCE_NLSTEXT ((HKEY)((LONG)0x80000060))
-+# endif
-+#endif
-+
- namespace G3D {
-
- // static helpers
-diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp
-index f6b0e03..281104d 100644
---- a/dep/g3dlite/source/System.cpp
-+++ b/dep/g3dlite/source/System.cpp
-@@ -564,7 +564,7 @@ void System::getStandardProcessorExtensions() {
- #endif
- }
-
--#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memcpy SIMD to all platforms")
- /** Michael Herf's fast memcpy */
- void memcpyMMX(void* dst, const void* src, int nbytes) {
-@@ -615,7 +615,7 @@ void memcpyMMX(void* dst, const void* src, int nbytes) {
- #endif
-
- void System::memcpy(void* dst, const void* src, size_t numBytes) {
--#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- memcpyMMX(dst, src, numBytes);
- #else
- ::memcpy(dst, src, numBytes);
-@@ -625,7 +625,7 @@ void System::memcpy(void* dst, const void* src, size_t numBytes) {
-
- /** Michael Herf's fastest memset. n32 must be filled with the same
- character repeated. */
--#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memfill SIMD to all platforms")
-
- // On x86 processors, use MMX
-@@ -664,7 +664,7 @@ void memfill(void *dst, int n32, unsigned long i) {
-
-
- void System::memset(void* dst, uint8 value, size_t numBytes) {
--#if defined(G3D_WIN32) && !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit Windows platforms */
-+#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- uint32 v = value;
- v = v + (v << 8) + (v << 16) + (v << 24);
- G3D::memfill(dst, v, numBytes);
-@@ -1696,7 +1696,7 @@ std::string System::currentDateString() {
-
- // VC on Intel
- void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
--#if !defined(G3D_64BIT) /* G3DFIX: Don't check if on 64-bit platform */
-+#if !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit platforms or using MinGW */
- // Can't copy from assembler direct to a function argument (which is on the stack) in VC.
- uint32 a,b,c,d;
-
diff --git a/dep/g3dlite/G3D-v8.0_hotfix7.diff b/dep/g3dlite/G3D-v8.0_hotfix7.diff
deleted file mode 100644
index 00ab78f5c7c..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix7.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dep/g3dlite/source/Matrix4.cpp b/dep/g3dlite/source/Matrix4.cpp
-index 2ce14f6..fbc918f 100644
---- a/dep/g3dlite/source/Matrix4.cpp
-+++ b/dep/g3dlite/source/Matrix4.cpp
-@@ -382,7 +382,7 @@ bool Matrix4::operator==(const Matrix4& other) const {
- // If the bit patterns are identical, they must be
- // the same matrix. If not, they *might* still have
- // equal elements due to floating point weirdness.
-- if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
-+ if (memcmp(this, &other, sizeof(Matrix4)) == 0) {
- return true;
- }
-
diff --git a/dep/g3dlite/G3D-v8.0_hotfix8.diff b/dep/g3dlite/G3D-v8.0_hotfix8.diff
deleted file mode 100644
index 438fd95f77c..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix8.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/Vector3int32.h b/dep/g3dlite/include/G3D/Vector3int32.h
-index 2f256ea..c1a6b21 100644
---- a/dep/g3dlite/include/G3D/Vector3int32.h
-+++ b/dep/g3dlite/include/G3D/Vector3int32.h
-@@ -74,7 +74,7 @@ public:
- inline Vector3int32& operator+=(const Vector3int32& other) {
- x += other.x;
- y += other.y;
-- z += other.y;
-+ z += other.z;
- return *this;
- }
-
diff --git a/dep/g3dlite/G3D-v8.0_hotfix9.diff b/dep/g3dlite/G3D-v8.0_hotfix9.diff
deleted file mode 100644
index a9021981e1c..00000000000
--- a/dep/g3dlite/G3D-v8.0_hotfix9.diff
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/dep/g3dlite/include/G3D/g3dmath.h b/dep/g3dlite/include/G3D/g3dmath.h
-index b0c98ae..4be723c 100644
---- a/dep/g3dlite/include/G3D/g3dmath.h
-+++ b/dep/g3dlite/include/G3D/g3dmath.h
-@@ -30,7 +30,7 @@
- #include <limits>
- #include <stdlib.h>
-
--#ifdef _MSC_VER
-+#if defined(_MSC_VER) && (_MSC_VER < 1000)
- // Visual Studio is missing inttypes.h
- # ifndef PRId64
- # define PRId64 "I64d"
diff --git a/dep/g3dlite/G3D-v9.0 hotfix1.diff b/dep/g3dlite/G3D-v9.0 hotfix1.diff
new file mode 100644
index 00000000000..cd0261d43ad
--- /dev/null
+++ b/dep/g3dlite/G3D-v9.0 hotfix1.diff
@@ -0,0 +1,475 @@
+Index: G3D9/G3D.lib/include/G3D/debugAssert.h
+===================================================================
+--- G3D9/G3D.lib/include/G3D/debugAssert.h (revision 4036)
++++ G3D9/G3D.lib/include/G3D/debugAssert.h (working copy)
+@@ -39,10 +39,12 @@
+ #ifdef G3D_LINUX
+ // Needed so we can define a global display
+ // pointer for debugAssert.
++#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ #include <X11/Xlib.h>
+ #include <X11/Xutil.h>
+ #include <X11/Xatom.h>
+ #endif
++#endif
+
+
+ /**
+@@ -178,6 +180,7 @@
+ namespace G3D { namespace _internal {
+
+ #ifdef G3D_LINUX
++#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ /**
+ A pointer to the X11 display. Initially NULL. If set to a
+ non-null value (e.g. by SDLWindow), debugAssert attempts to use
+@@ -194,6 +197,7 @@
+ */
+ extern Window x11Window;
+ #endif
++#endif
+
+ /**
+ Pops up an assertion dialog or prints an assertion
+Index: G3D9/G3D.lib/include/G3D/g3dmath.h
+===================================================================
+--- G3D9/G3D.lib/include/G3D/g3dmath.h (revision 4036)
++++ G3D9/G3D.lib/include/G3D/g3dmath.h (working copy)
+@@ -31,7 +31,7 @@
+ #include <stdlib.h>
+ #include <stdint.h>
+
+-#ifdef _MSC_VER
++#if defined(_MSC_VER) && (_MSC_VER < 1000)
+ // Visual Studio is missing inttypes.h
+ # ifndef PRId64
+ # define PRId64 "I64d"
+Index: G3D9/G3D.lib/include/G3D/platform.h
+===================================================================
+--- G3D9/G3D.lib/include/G3D/platform.h (revision 4036)
++++ G3D9/G3D.lib/include/G3D/platform.h (working copy)
+@@ -62,6 +62,11 @@
+
+ #ifdef _MSC_VER
+ # define G3D_WINDOWS
++#elif defined(__MINGW32__)
++ #define G3D_WINDOWS
++ #undef __MSVCRT_VERSION__
++ #define __MSVCRT_VERSION__ 0x0601
++ #include <windows.h>
+ #elif defined(__FreeBSD__) || defined(__OpenBSD__)
+ #define G3D_FREEBSD
+ #define G3D_LINUX
+@@ -68,7 +73,7 @@
+ #elif defined(__linux__)
+ #define G3D_LINUX
+ #elif defined(__APPLE__)
+- #define G3D_OSX
++ #define G3D_LINUX
+
+ // Prevent OS X fp.h header from being included; it defines
+ // pi as a constant, which creates a conflict with G3D
+@@ -80,9 +85,6 @@
+ /** \def G3D_64BIT */
+ /** \def G3D_32BIT */
+
+-#ifndef _MSC_VER
+-# define override
+-#endif
+
+
+ /** Define the g++ thread-local syntax on all platforms (since the MSVC version would be hard to emulate with a macro) */
+Index: G3D9/G3D.lib/source/BinaryInput.cpp
+===================================================================
+--- G3D9/G3D.lib/source/BinaryInput.cpp (revision 4036)
++++ G3D9/G3D.lib/source/BinaryInput.cpp (working copy)
+@@ -38,8 +38,10 @@
+ #include "G3D/fileutils.h"
+ #include "G3D/Log.h"
+ #include "G3D/FileSystem.h"
+-#include "../../zlib.lib/include/zlib.h"
++#include <zlib.h>
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ #include "../../zip.lib/include/zip.h"
++#endif
+ #include <cstring>
+
+ namespace G3D {
+@@ -126,6 +128,7 @@
+
+ setEndian(fileEndian);
+
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ std::string zipfile;
+ if (FileSystem::inZipfile(m_filename, zipfile)) {
+ // Load from zipfile
+@@ -162,7 +165,7 @@
+ m_freeBuffer = true;
+ return;
+ }
+-
++#endif
+ // Figure out how big the file is and verify that it exists.
+ m_length = FileSystem::size(m_filename);
+
+Index: G3D9/G3D.lib/source/BinaryOutput.cpp
+===================================================================
+--- G3D9/G3D.lib/source/BinaryOutput.cpp (revision 4036)
++++ G3D9/G3D.lib/source/BinaryOutput.cpp (working copy)
+@@ -14,7 +14,7 @@
+ #include "G3D/FileSystem.h"
+ #include "G3D/stringutils.h"
+ #include "G3D/Array.h"
+-#include "../../zlib.lib/include/zlib.h"
++#include <zlib.h>
+ #include "G3D/Log.h"
+ #include <cstring>
+
+Index: G3D9/G3D.lib/source/debugAssert.cpp
+===================================================================
+--- G3D9/G3D.lib/source/debugAssert.cpp (revision 4036)
++++ G3D9/G3D.lib/source/debugAssert.cpp (working copy)
+@@ -37,9 +37,11 @@
+ AssertionHook _failureHook = _handleErrorCheck_;
+
+ #ifdef G3D_LINUX
++#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ Display* x11Display = NULL;
+ Window x11Window = 0;
+ #endif
++#endif
+
+
+ #ifdef G3D_WINDOWS
+@@ -250,6 +252,7 @@
+ ClipCursor(NULL);
+
+ #elif defined(G3D_LINUX)
++#if 0 /* G3DFIX: Disabled to avoid requirement for X11 libraries */
+ if (x11Display != NULL) {
+ XUngrabPointer(x11Display, CurrentTime);
+ XUngrabKeyboard(x11Display, CurrentTime);
+@@ -264,6 +267,7 @@
+ XAllowEvents(x11Display, AsyncPointer, CurrentTime);
+ XFlush(x11Display);
+ }
++#endif
+ #elif defined(G3D_OSX)
+ // TODO: OS X
+ #endif
+Index: G3D9/G3D.lib/source/FileSystem.cpp
+===================================================================
+--- G3D9/G3D.lib/source/FileSystem.cpp (revision 4036)
++++ G3D9/G3D.lib/source/FileSystem.cpp (working copy)
+@@ -12,7 +12,9 @@
+ #include "G3D/fileutils.h"
+ #include <sys/stat.h>
+ #include <sys/types.h>
+-#include "zip.h"
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
++ #include "zip.h"
++#endif
+ #include "G3D/g3dfnmatch.h"
+ #include "G3D/BinaryInput.h"
+ #include "G3D/BinaryOutput.h"
+@@ -23,8 +25,11 @@
+
+ // Needed for _findfirst
+ # include <io.h>
+-
++# ifdef __MINGW32__
++# define stat64 stat
++# else
+ # define stat64 _stat64
++# endif
+ #else
+ # include <dirent.h>
+ # include <fnmatch.h>
+@@ -81,6 +86,7 @@
+
+
+ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& _pathInsideZipfile) {
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ const std::string& pathInsideZipfile = FilePath::canonicalize(_pathInsideZipfile);
+ struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
+ debugAssert(z);
+@@ -131,6 +137,7 @@
+
+ zip_close(z);
+ z = NULL;
++#endif
+ }
+
+
+@@ -574,6 +581,7 @@
+ int result = stat64(filename.c_str(), &st);
+
+ if (result == -1) {
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ std::string zip, contents;
+ if (zipfileExists(filename, zip, contents)) {
+ int64 requiredMem;
+@@ -591,8 +599,11 @@
+ zip_close(z);
+ return requiredMem;
+ } else {
++#endif
+ return -1;
+- }
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
++ }
++#endif
+ }
+
+ return st.st_size;
+Index: G3D9/G3D.lib/source/fileutils.cpp
+===================================================================
+--- G3D9/G3D.lib/source/fileutils.cpp (revision 4036)
++++ G3D9/G3D.lib/source/fileutils.cpp (working copy)
+@@ -21,7 +21,9 @@
+
+ #include <sys/stat.h>
+ #include <sys/types.h>
+-#include "zip.h"
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
++ #include "zip.h"
++#endif
+
+ #ifdef G3D_WINDOWS
+ // Needed for _getcwd
+@@ -133,6 +135,7 @@
+ // In zipfile
+ FileSystem::markFileUsed(zipfile);
+
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(filename.substr(zipfile.length() + 1));
+ struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
+@@ -160,6 +163,7 @@
+ System::alignedFree(buffer);
+ }
+ zip_close( z );
++#endif
+ }
+
+ return s;
+@@ -171,6 +175,7 @@
+ int result = _stat(filename.c_str(), &st);
+
+ if (result == -1) {
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ std::string zip, contents;
+ if(zipfileExists(filename, zip, contents)){
+ int64 requiredMem;
+@@ -190,6 +195,9 @@
+ } else {
+ return -1;
+ }
++#else
++ return -1;
++#endif
+ }
+
+ return st.st_size;
+@@ -286,6 +294,7 @@
+
+ ///////////////////////////////////////////////////////////////////////////////
+
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ /* Helper methods for zipfileExists()*/
+ // Given a string (the drive) and an array (the path), computes the directory
+ static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
+@@ -319,12 +328,13 @@
+ }
+ return true;
+ }
++#endif
+
+
+ /** If no zipfile exists, outZipfile and outInternalFile are unchanged */
+ bool zipfileExists(const std::string& filename, std::string& outZipfile,
+ std::string& outInternalFile){
+-
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ Array<std::string> path;
+ std::string drive, base, ext, zipfile, infile;
+ parseFilename(filename, drive, path, base, ext);
+@@ -386,7 +396,7 @@
+ }
+
+ }
+-
++#endif
+ // not a valid directory structure ever,
+ // obviously no .zip was found within the path
+ return false;
+@@ -671,7 +681,7 @@
+ # endif
+ }
+
+-
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ /**
+ @param path The zipfile name (no trailing slash)
+ @param prefix Directory inside the zipfile. No leading slash, must have trailing slash if non-empty.
+@@ -722,6 +732,7 @@
+ }
+ }
+ }
++#endif
+
+
+ static void getFileOrDirListZip(const std::string& path,
+@@ -729,6 +740,7 @@
+ Array<std::string>& files,
+ bool wantFiles,
+ bool includePath){
++#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ struct zip *z = zip_open( path.c_str(), ZIP_CHECKCONS, NULL );
+
+ Set<std::string> fileSet;
+@@ -744,6 +756,7 @@
+ zip_close( z );
+
+ fileSet.getMembers(files);
++#endif
+ }
+
+
+Index: G3D9/G3D.lib/source/Matrix4.cpp
+===================================================================
+--- G3D9/G3D.lib/source/Matrix4.cpp (revision 4036)
++++ G3D9/G3D.lib/source/Matrix4.cpp (working copy)
+@@ -405,7 +405,7 @@
+ // If the bit patterns are identical, they must be
+ // the same matrix. If not, they *might* still have
+ // equal elements due to floating point weirdness.
+- if (memcmp(this, &other, sizeof(Matrix4) == 0)) {
++ if (memcmp(this, &other, sizeof(Matrix4)) == 0) {
+ return true;
+ }
+
+Index: G3D9/G3D.lib/source/prompt.cpp
+===================================================================
+--- G3D9/G3D.lib/source/prompt.cpp (revision 4036)
++++ G3D9/G3D.lib/source/prompt.cpp (working copy)
+@@ -21,6 +21,7 @@
+ # define _getch getchar
+ #endif
+
++#if 0 /* G3DFIX: exclude GUI prompt code */
+ #ifdef G3D_OSX
+
+ /*#ifdef __LP64__
+@@ -37,9 +38,11 @@
+ */
+
+ #endif
++#endif /* G3DFIX: exclude GUI prompt code */
+
+ namespace G3D {
+
++#if 0 /* G3DFIX: exclude GUI prompt code */
+ #ifdef G3D_WINDOWS
+
+ namespace _internal {
+@@ -469,6 +472,7 @@
+ }
+
+ #endif
++#endif /* G3DFIX: exclude GUI prompt code */
+
+
+ /**
+@@ -531,6 +535,7 @@
+ return c;
+ }
+
++#if 0 /* G3DFIX: exclude GUI prompt code */
+ #ifdef G3D_OSX
+
+ static int guiPrompt
+@@ -544,6 +549,7 @@
+
+ #endif
+
++#endif /* G3DFIX: exclude GUI prompt code */
+ int prompt(
+ const char* windowTitle,
+ const char* prompt,
+@@ -550,7 +556,7 @@
+ const char** choice,
+ int numChoices,
+ bool useGui) {
+-
++#if 0 /* G3DFIX: exclude GUI prompt code */
+ #ifdef G3D_WINDOWS
+ if (useGui) {
+ // Build the message box
+@@ -566,6 +572,7 @@
+ return result;
+ }
+ #endif
++#endif /* G3DFIX: exclude GUI prompt code */
+ return textPrompt(windowTitle, prompt, choice, numChoices);
+ }
+
+Index: G3D9/G3D.lib/source/RegistryUtil.cpp
+===================================================================
+--- G3D9/G3D.lib/source/RegistryUtil.cpp (revision 4036)
++++ G3D9/G3D.lib/source/RegistryUtil.cpp (working copy)
+@@ -16,6 +16,14 @@
+ #include "G3D/RegistryUtil.h"
+ #include "G3D/System.h"
+
++#ifdef __MINGW32__
++# ifndef HKEY_PERFORMANCE_TEXT
++# define HKEY_PERFORMANCE_TEXT ((HKEY)((LONG)0x80000050))
++# endif
++# ifndef HKEY_PERFORMANCE_NLSTEXT
++# define HKEY_PERFORMANCE_NLSTEXT ((HKEY)((LONG)0x80000060))
++# endif
++#endif
+ namespace G3D {
+
+ // static helpers
+Index: G3D9/G3D.lib/source/System.cpp
+===================================================================
+--- G3D9/G3D.lib/source/System.cpp (revision 4036)
++++ G3D9/G3D.lib/source/System.cpp (working copy)
+@@ -587,7 +587,7 @@
+ #endif
+ }
+
+-#if defined(G3D_WINDOWS) && defined(_M_IX86)
++#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ // 32-bit
+ /** Michael Herf's fast memcpy. Assumes 16-byte alignment */
+ void memcpyMMX(void* dst, const void* src, int nbytes) {
+@@ -641,7 +641,7 @@
+ #endif
+
+ void System::memcpy(void* dst, const void* src, size_t numBytes) {
+-#if defined(G3D_WINDOWS) && defined(_M_IX86)
++#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ // The overhead of our memcpy seems to only be worthwhile on large arrays
+ if (((size_t)dst % 16 == 0) && ((size_t)src % 16 == 0) && (numBytes > 3400000)) {
+ memcpyMMX(dst, src, numBytes);
+@@ -656,7 +656,7 @@
+
+ /** Michael Herf's fastest memset. n32 must be filled with the same
+ character repeated. */
+-#if defined(G3D_WINDOWS) && defined(_M_IX86)
++#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ // On x86 processors, use MMX
+ void memfill(void *dst, int n32, unsigned long i) {
+
+@@ -694,7 +694,7 @@
+
+ void System::memset(void* dst, uint8 value, size_t numBytes) {
+ alwaysAssertM(dst != NULL, "Cannot memset NULL address.");
+-#if defined(G3D_WINDOWS) && defined(_M_IX86)
++#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ if ((((size_t)dst % 16) == 0) && (numBytes >= 512*1024)) {
+ uint32 v = value;
+ v = v + (v << 8) + (v << 16) + (v << 24);
diff --git a/dep/g3dlite/Readme.txt b/dep/g3dlite/Readme.txt
index 739f6985090..c250c77c71b 100644
--- a/dep/g3dlite/Readme.txt
+++ b/dep/g3dlite/Readme.txt
@@ -10,3 +10,4 @@ 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
diff --git a/dep/g3dlite/include/G3D/AABox.h b/dep/g3dlite/include/G3D/AABox.h
index d57320d73eb..7a47ea63aa2 100644
--- a/dep/g3dlite/include/G3D/AABox.h
+++ b/dep/g3dlite/include/G3D/AABox.h
@@ -1,29 +1,31 @@
/**
- @file AABox.h
+ \file G3D/AABox.h
Axis-aligned box class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-01-10
- @edited 2009-02-10
+ \created 2004-01-10
+ \edited 2013-04-13
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_AABOX_H
-#define G3D_AABOX_H
+#ifndef G3D_AABox_h
+#define G3D_AABox_h
#include "G3D/platform.h"
-#include "G3D/Vector3.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.
*/
@@ -34,66 +36,109 @@ private:
/** Optional argument placeholder */
static int dummy;
- Vector3 lo;
- Vector3 hi;
+ /** NaN if empty */
+ Point3 lo;
+
+ /** NaN if empty */
+ Point3 hi;
public:
- /** Does not initialize the fields */
- inline AABox() {}
+ /** Creates the empty bounds, i.e., an empty set of points. */
+ AABox() : lo(fnan(), fnan(), fnan()), hi(fnan(), fnan(), fnan()) {}
/**
- Constructs a zero-area AABox at v.
+ Constructs a zero-volume AABox at v.
*/
- inline explicit AABox(const Vector3& 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>
*/
- inline AABox(const Vector3& low, const Vector3& high) {
+ 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 Vector3& low, const Vector3& high) {
+ 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
+ Grows to include the bounds of \a a
*/
inline void merge(const AABox& a) {
- lo = lo.min(a.lo);
- hi = hi.max(a.hi);
+ 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 Vector3& a) {
- lo = lo.min(a);
- hi = hi.max(a);
+ 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 lo.isFinite() && hi.isFinite();
+ return isEmpty() || (lo.isFinite() && hi.isFinite());
}
- inline const Vector3& low() const {
+ /** Returns not-a-number if empty */
+ inline const Point3& low() const {
return lo;
}
- inline const Vector3& high() const {
+ /** Returns not-a-number if empty */
+ inline const Point3& high() const {
return hi;
}
@@ -110,25 +155,33 @@ public:
static const AABox& zero();
+ static const AABox& empty();
+
/**
- Returns the centroid of the box.
+ Returns the centroid of the box (NaN if empty)
*/
- inline Vector3 center() const {
+ inline Point3 center() const {
return (lo + hi) * 0.5;
}
- Vector3 corner(int index) const;
+ 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;
}
@@ -140,46 +193,46 @@ public:
*/
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
+ /**
+ 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.
+ <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 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
+ @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;
+ */
+ 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;
+ 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 {
@@ -192,8 +245,7 @@ public:
(other.lo.z >= lo.z);
}
- inline bool contains(
- const Vector3& point) const {
+ inline bool contains(const Point3& point) const {
return
(point.x >= lo.x) &&
(point.y >= lo.y) &&
@@ -204,31 +256,42 @@ public:
}
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;
}
- Vector3 randomInteriorPoint() const;
+ Point3 randomInteriorPoint() const;
- Vector3 randomSurfacePoint() 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 class Sphere& other) const;
+ bool intersects(const Sphere& other) const;
/** Return the intersection of the two boxes */
AABox intersect(const AABox& other) const {
- Vector3 H = hi.min(other.hi);
- Vector3 L = lo.max(other.lo).min(H);
- return AABox(L, H);
+ 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 {
@@ -236,11 +299,19 @@ public:
}
inline bool operator==(const AABox& b) const {
- return (lo == b.lo) && (hi == b.hi);
+ if (isEmpty() && b.isEmpty()) {
+ return true;
+ } else {
+ return (lo == b.lo) && (hi == b.hi);
+ }
}
inline bool operator!=(const AABox& b) const {
- return !((lo == b.lo) && (hi == b.hi));
+ if (isEmpty()) {
+ return b.isEmpty();
+ } else {
+ return !((lo == b.lo) && (hi == b.hi));
+ }
}
inline AABox operator+(const Vector3& v) const {
diff --git a/dep/g3dlite/include/G3D/Any.h b/dep/g3dlite/include/G3D/Any.h
index e2d0fbe7e62..25af58d1ec3 100644
--- a/dep/g3dlite/include/G3D/Any.h
+++ b/dep/g3dlite/include/G3D/Any.h
@@ -1,13 +1,13 @@
/**
- @file Any.h
+ \file Any.h
- @author Morgan McGuire, Shawn Yarbrough, and Corey Taylor
- @maintainer Morgan McGuire
+ \author Morgan McGuire, Shawn Yarbrough, and Corey Taylor
+ \maintainer Morgan McGuire
- @created 2006-06-11
- @edited 2010-03-16
+ \created 2006-06-11
+ \edited 2013-03-29
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -17,13 +17,13 @@
#include "G3D/platform.h"
#include "G3D/Table.h"
#include "G3D/Array.h"
-#include "G3D/Set.h"
#include "G3D/AtomicInt32.h"
#include "G3D/stringutils.h"
#include <string>
// needed for Token
#include "G3D/TextInput.h"
+#include "G3D/TextOutput.h"
#ifdef verify
#undef verify
@@ -38,7 +38,8 @@ class TextOutput;
Any encodes typed, structured data and can serialize it to a human
readable format that is very similar to the Python language's data
-syntax. It is well-suited for quickly creating human-readable file
+syntax, and fully supports Python's data syntax as well.
+It is well-suited for quickly creating human-readable file
formats, especially since deserialization and serialization preserve
comments and an Any can tell you what file and line it came from. The
syntax allows most C++ editors to properly highlight Any files, and
@@ -61,7 +62,7 @@ Sample File:
position = Vector3(1.0, -1.0, 0.0),
video = { format = "RGB8", size = (320, 200)},
- material = #include("rocks.mat")
+ material = \#include("rocks.mat")
}
</pre>
@@ -79,7 +80,8 @@ The custom serialization format was chosen to be terse, easy for
humans to read, and easy for machines to parse. It was specifically
chosen over formats like XML, YAML, JSON, S-expressions, and Protocol
Buffers, although there is no reason you could not write readers and
-writers for G3D::Any that support those.
+writers for G3D::Any that support those. Any also currently supports
+the JSON format.
G3D::Any assumes that structures do not contain cycles; it is an
error to create a structure like:
@@ -91,6 +93,17 @@ x.array().append(x); // don't do this!
although no exception will be thrown at runtime during that append.
+\section includes
+
+When parsing an Any from a file, the syntax
+<code>\#include(<i>filename</i>)</code> allows subsitution of the contents of
+<i>filename</i> for any single expression in an Any. The filename is interpreted
+relative to the file being parsed, and inside of the included file, relative filenames
+are interpreted with respect to the included file (and so on, recursively for nested
+inclusion).
+
+Filenames are resolved with System::resolve and then System::findDataFile if not found,
+so they may contain environment variables.
\section Parsing
@@ -117,24 +130,12 @@ Vector3::Vector3(const Any& any) {
}
</pre>
-It is often convenient to iterate through the table portion:
-
-<pre>
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& k = toLower(it->key);
- if (key == "hello") {
- ...
- } else if (key == "goodbye") {
- ...
- } else {
- any.verify(false, "Unsupported key: " + it->key);
- }
- }
-</pre>
+It is often convenient to iterate through the table portion using G3D::AnyTableReader.
\section BNF
Serialized format BNF:
+\htmlonly
<pre>
identifier ::= (letter | "_") (letter | digit | "_")*
identifier-op ::= "::" | "->" | "."
@@ -145,18 +146,19 @@ comment ::= C++ single or multi-line comments
separator ::= "," | ";"
number ::= <legal C printf number format>
-string ::= <legal C double-quoted string; backslashes must be escaped>
+string ::= <legal C double-quoted or unquoted string; backslashes must be escaped>
boolean ::= "True" | "False"
-none ::= "None"
-array ::= ("(" | "[") [ value (separator value)* [separator] ] (")" | "]")
-pair ::= (identifier | string) "=" value
-table ::= "{" [ pair (separator pair)* [separator] ] "}"
+nil ::= "Nil" <not case sensitive> | "None" <case sensitive>
+array ::= ("(" | "[" | "{") [value (separator value)* [separator] ] (")" | "]" | "}")
+pair ::= (identifier | string) ("=" | ":") value
+table ::= ("(" | "[" | "{") [ pair (separator pair)* [separator] ] (")" | "]" | "}")
named-array ::= identifier-exp array
named-table ::= identifier-exp table
include ::= "#" "include" "(" string ")"
-value ::= [comment] (none | number | boolean | string | array | table | named-array | named-table | include)
+value ::= [comment] (nil | number | boolean | string | array | table | named-array | named-table | include)
</pre>
+\endhtmlonly
Except for single-line comments, whitespace is not significant.
All parsing is case-insensitive.
@@ -167,7 +169,7 @@ can only appear in the locations where a value is expected. This means
that it cannot yield more than one element of an array and cannot serve
as the pair in a table.
-The deserializer allows the substitution of [] for () when writing
+The deserializer allows the substitution of [] or {} for () when writing
tuples and ";" for ",". These are convenient when mimicing a
programming language, e.g., <code>"[ printf("hello world."); clearScreen();]"</code>
parses as an array containing two named arrays within it. The
@@ -176,11 +178,13 @@ which also convenient when commenting out the last element.
The serializer indents four spaces for each level of nesting.
Tables are written with the keys in alphabetic order.
+
+\sa G3D::AnyTableReader
*/
class Any {
public:
- enum Type {NONE, BOOLEAN, NUMBER, STRING, ARRAY, TABLE};
+ enum Type {NIL, BOOLEAN, NUMBER, STRING, ARRAY, TABLE, EMPTY_CONTAINER};
static std::string toString(Type t);
@@ -208,7 +212,7 @@ private:
/** Called from deserialize() */
static void deserializeComment(TextInput& ti, Token& token, std::string& comment);
- /** NONE, BOOLEAN, and NUMBER are stored directly in the Any */
+ /** NIL, BOOLEAN, and NUMBER are stored directly in the Any */
union SimpleValue {
bool b;
double n;
@@ -218,6 +222,11 @@ private:
inline SimpleValue(double x) : n(x) {}
};
+ /** The three options for Data::bracket */
+ static const char* PAREN;
+ static const char* BRACKET;
+ static const char* BRACE;
+
class Data {
public:
/** ARRAY, TABLE, or STRING value only. NULL otherwise. */
@@ -240,6 +249,16 @@ private:
std::string name;
+ /** If this Any was created by parsing an #include expression and
+ has not been modified since, this is the original comment and
+ include statement, as
+ it originally appeared in the file (e.g., it may contain a relative
+ filename). If this is non-empty, then when serialized, this
+ Any will turn into an #include expression instead of unparsing
+ its contents of the any.
+ */
+ std::string includeLine;
+
/** For STRING, ARRAY and TABLE 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
@@ -249,10 +268,16 @@ private:
Source source;
+ /** Two-character string of "{}", "[]", or "()"; to be used when unparsing. */
+ const char* bracket;
+
+ /** ';' or ',' separator to be used when unparsing */
+ char separator;
+
private:
/** Called by create() */
- inline Data(Type t) : type(t), referenceCount(1) {}
+ inline Data(Type t, const char* b, char s) : type(t), referenceCount(1), bracket(b), separator(s) {}
/** Called by destroy */
~Data();
@@ -261,12 +286,11 @@ private:
/** Clones the argument */
static Data* create(const Data* d);
- static Data* create(Type t);
+ static Data* create(Type t, const char* b = NULL, char s = '\0');
/** Free d, invoking its destructor and freeing the memory for
the value. */
static void destroy(Data* d);
-
};
/** If not empty, this Any was created from operator[] on a table
@@ -283,12 +307,11 @@ private:
SimpleValue m_simpleValue;
mutable Data* m_data;
- /** Called before every read operation to ensure that this object
- is not a placeholder. */
+ /** Called before every read operation. */
void beforeRead() const;
- /** Called before every write operation to wipe the placeholder
- status. */
+ /** Called before every write operation to this Any. Wipes the placeholder
+ status and includedFrom entry. */
void beforeWrite();
/** Decrements the reference count (if there is one). If the
@@ -316,43 +339,61 @@ private:
/** Read the name of a named Array or Table. */
static void deserializeName(TextInput& ti, Token& token, std::string& name);
- /** Read until a comma is consumed or a close paren is hit, and
+ /** Read until a separator is consumed or a close paren is hit, and
return that token. Considers the passed in token to be the first
value read. */
- static void readUntilCommaOrClose(TextInput& ti, Token& token);
+ static void readUntilSeparatorOrClose(TextInput& ti, Token& token);
/** Construct an Any that is a proxy for a table fetch from \a data.
This proxy can be copied exactly once on return from operator[].*/
Any(const std::string& key, Data* data);
- inline bool isPlaceholder() const {
+ bool isPlaceholder() const {
return ! m_placeholderName.empty();
}
+
+ void _append(const Any& v0);
+ void _append(const Any& v0, const Any& v1);
+ void _append(const Any& v0, const Any& v1, const Any& v2);
+ void _append(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
+ Any _get(const std::string& key, const Any& defaultVal) const;
+ void _set(const std::string& key, const Any& val);
-public:
+ void _parse(const std::string& src);
- /** Base class for all Any exceptions.*/
- class Exception {
- public:
- virtual ~Exception() {}
- };
+public:
/** Thrown by operator[] when a key is not present in a const table. */
class KeyNotFound : public ParseError {
public:
std::string key;
+
+ KeyNotFound(const Data* data) {
+ if (data) {
+ filename = data->source.filename;
+ line = data->source.line;
+ character = data->source.character;
+ }
+ }
};
/** Thrown by operator[] when an array index is not present. */
- class IndexOutOfBounds : public Exception {
+ class IndexOutOfBounds : public ParseError {
public:
int index;
int size;
- inline IndexOutOfBounds() : index(0), size(0) {}
- inline IndexOutOfBounds(int i, int s) : index(i), size(s) {}
+ IndexOutOfBounds() : index(0), size(0) {}
+ IndexOutOfBounds(const Data* data, int i, int s) : index(i), size(s) {
+ if (data) {
+ filename = data->source.filename;
+ line = data->source.line;
+ character = data->source.character;
+ }
+ message = format("Index out of bounds: index = %d, array size = %d", i, s);
+ }
};
- /** NONE constructor */
+ /** NIL constructor */
Any();
/** Deserialize */
@@ -361,108 +402,133 @@ public:
Any(const Any& x);
/** NUMBER constructor */
- Any(double x);
+ explicit Any(double x);
+
+ explicit Any(float x);
-#ifdef G3D_32BIT
+ #if defined(G3D_32Bit) || defined(_MSC_VER)
/** NUMBER constructor */
- Any(int64 x);
-#endif // G3D_32BIT
+ explicit Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {}
+ #endif
-#if 0
/** NUMBER constructor */
- Any(int32 x);
-#endif // 0
+ explicit Any(long x);
/** NUMBER constructor */
- Any(long x);
+ explicit Any(int x);
/** NUMBER constructor */
- Any(int x);
+ explicit Any(char x);
/** NUMBER constructor */
- Any(short x);
+ explicit Any(short x);
/** BOOLEAN constructor */
- Any(bool x);
+ explicit Any(bool x);
/** STRING constructor */
- Any(const std::string& x);
+ explicit Any(const std::string& x);
/** STRING constructor */
- Any(const char* x);
+ explicit Any(const char* x);
+
+ /** \a t must be ARRAY or TABLE
+ \param brackets must be "" (defaults to {} for table, () for array), "[]", "()", or "{}"
+ \param separator must be ';', ',', or '\0' (defaults to ',' for array and ';' for table)
+ */
+ explicit Any(Type t, const std::string& name = "", const std::string& brackets = "", const char separator = '\0');
+
+ /** Extensible constructor: call the toAny() method of any class. */
+ template<class T>
+ explicit Any(const T& v) : m_type(NIL), m_data(NULL) {
+ *this = v.toAny();
+ }
- /** \a t must be ARRAY or TABLE */
- Any(Type t, const std::string& name = "");
-
~Any();
/** Removes the comment and name */
Any& operator=(const Any& x);
- /** Removes the comment and name */
- Any& operator=(double x);
-
- /** Removes the comment and name */
- Any& operator=(int x);
-
- /** Removes the comment and name */
- Any& operator=(bool x);
+ /** \a t must be ARRAY, TABLE, or NIL. Removes the comment and name */
+ Any& operator=(Type t);
- /** Removes the comment and name */
- Any& operator=(const std::string& x);
+ /** Assigns from an array. Assumes that T can be converted to Any. Removes the comment and name */
+ template<class T>
+ Any& operator=(const Array<T>& array) {
+ *this = Any::ARRAY;
+ resize(array.size());
+ for (int i = 0; i < array.size(); ++i) {
+ this->operator [](i) = array[i];
+ }
+ return *this;
+ }
/** Removes the comment and name */
- Any& operator=(const char* x);
-
- /** \a t must be ARRAY, TABLE, or NONE. Removes the comment and name */
- Any& operator=(Type t);
+ template<class T>
+ Any& operator=(const T& v) {
+ *this = Any(v);
+ return *this;
+ }
Type type() const;
/** Same as deserialize or load, but operates on a string instead
of a stream or file.
- \sa deserialize, load
+ \sa deserialize, load, unparse
*/
- void parse(const std::string& src);
+ static Any parse(const std::string& src);
+
+ std::string unparse(const TextOutput::Settings& s = TextOutput::Settings()) const;
- std::string unparse() const;
+ /** \param allowCoercion If false, throws an error if the Any uses features that are not
+ supported by JSON such as named arrays. Otherwise, silently coerces to JSON. */
+ std::string unparseJSON(const TextOutput::Settings& s = TextOutput::Settings(), bool allowCoercion = true) const;
/** Comments appear before values when they are in serialized form.*/
const std::string& comment() const;
void setComment(const std::string& c);
- /** True if this is the NONE value */
- bool isNone() const;
+ /** True if this is the NIL value */
+ bool isNil() const;
/** Throws a ParseError exception if this is not a number */
double number() const;
+ float floatValue() const;
+
const std::string& string() const;
bool boolean() const;
- /** If a valid string, takes the string value and creates a fully qualified filename.
- If not found, the returned string is empty.
+ /** If a valid string, takes the string value and creates a fully
+ qualified filename.
The file is searched for the following ways:
- In the directory from which the Any was loaded.
- By calling System::findDataFile as you would with other data files.
+
+ Strings that begin with '<' and end with '>' are treated as
+ escape sequences and are returned unmodifed.
*/
- std::string resolveStringAsFilename() const;
+ std::string resolveStringAsFilename(bool errorIfNotFound = true) const;
/** If this is named ARRAY or TABLE, returns the name. */
const std::string& name() const;
- /** If this is named ARRAY or TABLE, returns true if the name begins with \a s. The comparision is case insensitive. */
+ /** If this is named ARRAY or TABLE, returns true if the name
+ begins with \a s. The comparision is case insensitive. */
bool nameBeginsWith(const std::string& s) const;
- /** If this is named ARRAY or TABLE, returns true if the name begins with \a s. The comparision is case insensitive. */
+ /** If this is named ARRAY or TABLE, returns true if the name
+ begins with \a s. The comparision is case insensitive. */
bool nameBeginsWith(const char* s) const;
- /** If this is named ARRAY or TABLE, returns true if the name is \a s. The comparision is case insensitive. */
+ /** If this is named ARRAY or TABLE, returns true if the name is
+ \a s. The comparision is case insensitive. */
bool nameEquals(const std::string& s) const;
- /** If this is named ARRAY or TABLE, returns true if the name is\a s. The comparision is case insensitive. */
+ /** If this is named ARRAY or TABLE, returns true if the name is\a
+ s. The comparision is case insensitive. */
bool nameEquals(const char* s) const;
/** \brief Set the name used when serializing an ARRAY or TABLE.
@@ -504,12 +570,29 @@ public:
/** Directly exposes the underlying data structure for an ARRAY. */
const Array<Any>& array() const;
- void append(const Any& v0);
- void append(const Any& v0, const Any& v1);
- void append(const Any& v0, const Any& v1, const Any& v2);
- void append(const Any& v0, const Any& v1, const Any& v2, const Any& v3);
- /** Directly exposes the underlying data structure for table.*/
+ template<class T0>
+ void append(const T0& v0) {
+ _append(Any(v0));
+ }
+
+ template<class T0, class T1>
+ void append(const T0& v0, const T1& v1) {
+ _append(Any(v0), Any(v1));
+ }
+
+ template<class T0, class T1, class T2>
+ void append(const T0& v0, const T1& v1, const T2& v2) {
+ _append(Any(v0), Any(v1), Any(v2));
+ }
+
+ template<class T0, class T1, class T2, class T3>
+ void append(const T0& v0, const T1& v1, const T2& v2, const T3& v3) {
+ _append(Any(v0), Any(v1), Any(v2), Any(v3));
+ }
+
+ /** Directly exposes the underlying data structure for table.
+ \sa G3D::AnyTableReader*/
const Table<std::string, Any>& table() const;
/** For a table, returns the element for \a key. Throws KeyNotFound
@@ -549,19 +632,25 @@ public:
Any& operator[](const std::string& key);
/** \copydoc Any::operator[](const std::string&) */
- Any& operator[](const char* key) {
+ inline Any& operator[](const char* key) {
return operator[](std::string(key));
}
/** For a table, returns the element for key \a x and \a
defaultVal if it does not exist. */
- const Any& get(const std::string& key, const Any& defaultVal) const;
+ template<class T>
+ Any get(const std::string& key, const T& defaultVal) const {
+ return _get(key, Any(defaultVal));
+ }
/** Returns true if this key is in the TABLE. Illegal to call on an object that is not a TABLE. */
bool containsKey(const std::string& key) const;
/** For a table, assigns the element for key k. */
- void set(const std::string& key, const Any& val);
+ template<class T>
+ void set(const std::string& key, const T& val) {
+ _set(key, Any(val));
+ }
/** for an ARRAY, resizes and returns the last element */
Any& next();
@@ -573,14 +662,64 @@ public:
/** True if the Anys are exactly equal, ignoring comments. Applies deeply on arrays and tables. */
bool operator==(const Any& x) const;
+
+ bool operator==(const std::string& s) const {
+ return *this == Any(s);
+ }
+
+ bool operator==(const double& v) const {
+ return *this == Any(v);
+ }
+
+ bool operator==(int v) const {
+ return *this == Any(v);
+ }
+
+ bool operator==(bool v) const {
+ return *this == Any(v);
+ }
+
bool operator!=(const Any& x) const;
+ bool operator!=(const std::string& s) const {
+ return *this != Any(s);
+ }
+
+ bool operator!=(const double& v) const {
+ return *this != Any(v);
+ }
+
+ bool operator!=(int v) const {
+ return *this != Any(v);
+ }
+
+ bool operator!=(bool v) const {
+ return *this != Any(v);
+ }
+
operator int() const;
+ operator uint32() const;
operator float() const;
operator double() const;
operator bool() const;
operator std::string() const;
+ operator char() const {
+ return char(int(*this));
+ }
+
+ operator uint8() const {
+ return uint8(int(*this));
+ }
+
+ operator int16() const {
+ return int16(int(*this));
+ }
+
+ operator uint16() const {
+ return uint16(int(*this));
+ }
+
/** Resize to \a n elements, where new elements are NIL
It is an error to call this method if this is not an Any::ARRAY */
void resize(int n);
@@ -591,33 +730,88 @@ public:
void clear();
/** Parse from a file.
- \sa deserialize, parse */
+ \sa deserialize, parse, fromFile, loadIfExists
+ */
void load(const std::string& filename);
+ /** Load a new Any from \a filename. \sa load, save, loadIfExists */
+ static Any fromFile(const std::string& filename);
+
+ /** Load \a filename file if it exists, otherwise do not modify this */
+ void loadIfExists(const std::string& filename);
+
/** Uses the serialize method. */
void save(const std::string& filename) const;
- void serialize(TextOutput& to) const;
+ void serialize(TextOutput& to, bool json = false, bool coerce = false) const;
+
+ void serialize(class BinaryOutput& b) const;
+
/** Parse from a stream.
\sa load, parse */
void deserialize(TextInput& ti);
+ void deserialize(class BinaryInput& b);
+
const Source& source() const;
+ /** Removes this key from the Any, which must be a table. */
+ void remove(const std::string& key);
+
+ /** Removes this key from the Any, which must be an array, and
+ shifts other elements down to maintain order. */
+ void remove(int index);
+
/** Throws a ParseError if \a value is false. Useful for quickly
creating parse rules in classes that deserialize from Any.
*/
void verify(bool value, const std::string& message = "") const;
- /** Verifies that the name <i>begins with</i> identifier \a n (case insensitive).
+ /** Verifies that the name is identifier \a n (case sensitive).
It may contain identifier operators after this */
void verifyName(const std::string& n) const;
- /** Verifies that the name <i>begins with</i> identifier \a n or \a m (case insensitive).
+ /** Verifies that the name is identifier \a n or \a m (case sensitive).
It may contain identifier operators after this */
void verifyName(const std::string& n, const std::string& m) const;
+ /** Verifies that the name is identifier \a n or \a m or \a p (case sensitive).
+ It may contain identifier operators after this */
+ void verifyName(const std::string& n, const std::string& m, const std::string& p) const;
+
+ /** Verifies that the name is identifier \a n or \a m or \a p or \a q (case sensitive).
+ It may contain identifier operators after this */
+ void verifyName(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r or \a s (case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s) const;
+
+ /** Verifies that the name <i>begins with</i> identifier \a n or \a m or \a p or \a q or \a r or \a s or \a t(case sensitive).
+ It may contain identifier operators after this */
+ void verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s, const std::string& t) const;
+
/** Verifies that the type is \a t. */
void verifyType(Type t) const;
@@ -630,14 +824,49 @@ public:
/** Verifies that the size is exactly \a s */
void verifySize(int s) const;
+ /** Assumes that Any(T) is well-defined, e.g., by T defining a
+ T::toAny() method. */
+ template<class T>
+ explicit Any(const Array<T>& array, const std::string& name = "") : m_type(ARRAY), m_data(NULL) {
+ setName(name);
+ resize(array.size());
+ for (int i = 0; i < array.size(); ++i) {
+ (*this)[i] = Any(array[i]);
+ }
+ }
+
+ /** Assumes that T defines T(const Any&) */
+ template<class T>
+ void getArray(Array<T>& array) const {
+ verifyType(ARRAY);
+ array.resize(size());
+ for (int i = 0; i < array.size(); ++i) {
+ array[i] = T((*this)[i]);
+ }
+ }
+
+ /** Assumes that T defines T(const Any&) */
+ template<class T>
+ void getTable(Table<std::string, T>& table) const {
+ verifyType(TABLE);
+ for (Table<std::string, Any>::Iterator it = this->table().begin(); it.isValid(); ++it) {
+ table.set(it.key(), T(it.value()));
+ }
+ }
+
private:
void deserializeTable(TextInput& ti);
void deserializeArray(TextInput& ti,const std::string& term);
+ /** Turns an empty container into a table or an array */
+ void become(const Type& t);
+
}; // class Any
+
+
/**
Convenient iteration over the keys of a Any::TABLE, usually
for implementing construction of an object from an Any.
@@ -647,14 +876,14 @@ private:
It is an error to consume the same element more than once from
the same iterator.
- <pre>
- AnyKeyIterator r(a);
- r.getIfPresent("enabled", enabled);
- r.getIfPresent("showSamples", showSamples);
- r.getIfPresent("showTiles", showTiles);
+ \code
+ AnyTableReader r(a);
+ r.getIfPresent("enabled", enabled);
+ r.getIfPresent("showSamples", showSamples);
+ r.get("showTiles", showTiles);
r.verifyDone();
- </pre>
+ \endcode
\beta
*/
@@ -665,44 +894,21 @@ private:
public:
/** Verifies that \a is a TABLE with the given \a name. */
- AnyTableReader(const std::string& name, const Any& a) : m_any(a) {
- try {
- m_any.verifyType(Any::TABLE);
- m_any.verifyName(name);
- } catch (const ParseError& e) {
- // If an exception is thrown, the destructors will not be
- // invoked automatically.
- m_any.~Any();
- m_alreadyRead.~Set();
- throw e;
- }
- }
+ AnyTableReader(const std::string& name, const Any& a);
/** Verifies that \a is a TABLE. */
- AnyTableReader(const Any& a) : m_any(a) {
- try {
- m_any.verifyType(Any::TABLE);
- } catch (const ParseError& e) {
- // If an exception is thrown, the destructors will not be
- // invoked automatically.
- m_any.~Any();
- m_alreadyRead.~Set();
- throw e;
- }
- }
+ AnyTableReader(const Any& a);
bool hasMore() const {
return m_any.size() > m_alreadyRead.size();
}
/** Verifies that all keys have been read. */
- void verifyDone() const {
- if (hasMore()) {
- // Generate all keys
- // Remove the ones we've read
- // Assert the rest
- // any.verify("");
- }
+ void verifyDone() const;
+
+ /** Return the underlying Any. */
+ const Any& any() const {
+ return m_any;
}
#if 0
@@ -714,30 +920,67 @@ public:
AnyKeyIterator& operator++();
#endif
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, std::string& v) {
+ v = m_any[s].string();
+ m_alreadyRead.insert(s);
+ }
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, uint8& v) {
+ v = uint8(m_any[s].number());
+ m_alreadyRead.insert(s);
+ }
+
+ /** \copydoc get(const std::string& s, ValueType& v) */
+ void get(const std::string& s, uint16& v) {
+ v = uint16(m_any[s].number());
+ m_alreadyRead.insert(s);
+ }
+
+ /** Read an entire array at once.*/
+ template<class T>
+ void get(const std::string& s, Array<T>& v) {
+ m_any[s].getArray(v);
+ m_alreadyRead.insert(s);
+ }
- /** If key \s appears in the any, reads its value into \a v and
+ template<class T>
+ void get(const std::string& s, Table<std::string, T>& v) {
+ m_any[s].getTable(v);
+ m_alreadyRead.insert(s);
+ }
+
+ /** If key \a s appears in the any, reads its value into \a v and
removes that key from the ones available to iterate over.
- If key \s does not appear in the any, throws a G3D::ParseError.
+ If key \a s does not appear in the any, throws a G3D::ParseError.
- Assumes that if key \s appears in the any it has not already been extracted
+ Assumes that if key \a s appears in the any it has not already been extracted
by this iterator. If it has been read before, an assertion will fail in debug mode.
*/
template<class ValueType>
void get(const std::string& s, ValueType& v) {
- v = m_any[s];
- m_alreadyRead.insert(toLower(s));
+ v = ValueType(m_any[s]);
+ m_alreadyRead.insert(s);
+ }
+
+ /** Same as get() */
+ const Any& operator[](const std::string& s) {
+ m_alreadyRead.insert(s);
+ return m_any[s];
}
/** Get the value associated with a key only if the key is actually present.
- If key \s appears in the any, reads its value into \a v and
+ If key \a s appears in the any, reads its value into \a v and
removes that key from the ones available to iterate over.
- If key \s does not appear in the any, does nothing.
+ If key \a s does not appear in the any, does nothing.
- Assumes that if key \s appears in the any it has not already been extracted
+ Assumes that if key \a s appears in the any it has not already been extracted
by this iterator. If it has been read before, an assertion will fail in debug mode.
\return True if the value was read.
@@ -745,7 +988,7 @@ public:
template<class ValueType>
bool getIfPresent(const std::string& s, ValueType& v) {
if (m_any.containsKey(s)) {
- debugAssertM(! m_alreadyRead.contains(toLower(s)), "read twice");
+ debugAssertM(! m_alreadyRead.contains(s), "read twice");
get(s, v);
return true;
@@ -753,8 +996,29 @@ public:
return false;
}
}
+
+ /** \return True if \a s is in the table and has not yet been read
+ using get() or getIfPresent(). */
+ bool containsUnread(const std::string& s) const {
+ return m_any.containsKey(s) && ! m_alreadyRead.contains(s);
+ }
+
};
} // namespace G3D
+
+/**
+ \def PARSE_ANY(expression)
+
+ \brief Create an G3D::Any from an unquoted string.
+
+ e.g.,
+ \code
+ Any x = PARSE_ANY( { a = 3.0; b = false; } );
+ \endcode
+ */
+#define PARSE_ANY(x) Any::parse(#x)
+
+
#endif
diff --git a/dep/g3dlite/include/G3D/AnyVal.h b/dep/g3dlite/include/G3D/AnyVal.h
deleted file mode 100644
index 8c1bc72f206..00000000000
--- a/dep/g3dlite/include/G3D/AnyVal.h
+++ /dev/null
@@ -1,512 +0,0 @@
-/**
- @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>&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>,
- <br>&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</code>r2c0<code>, </code>r2c1<code>, </code>r2c2<code>, </code>r2c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</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>&nbsp;&nbsp;&nbsp;</code>r1c0<code>, </code>r1c1<code>, </code>r1c2<code>, </code>r1c3<code>,
- <br>&nbsp;&nbsp;&nbsp;</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>&nbsp;</code><i>symbol<sub>1</sub></i><code> = </code><i>value<sub>1</sub></i>
- <br><code>&nbsp;</code>...
- <br><code>&nbsp;</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
diff --git a/dep/g3dlite/include/G3D/AreaMemoryManager.h b/dep/g3dlite/include/G3D/AreaMemoryManager.h
index d8d8f710359..5ff46505b0f 100644
--- a/dep/g3dlite/include/G3D/AreaMemoryManager.h
+++ b/dep/g3dlite/include/G3D/AreaMemoryManager.h
@@ -1,12 +1,12 @@
/**
- @file AreaMemoryManager.h
+ \file AreaMemoryManager.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-01-20
- @edited 2009-05-29
+ \created 2009-01-20
+ \edited 2010-10-29
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -57,7 +57,7 @@ private:
public:
- typedef ReferenceCountedPointer<AreaMemoryManager> Ref;
+ typedef shared_ptr<AreaMemoryManager> Ref;
/**
\param sizeHint Total amount of memory expected to be allocated.
diff --git a/dep/g3dlite/include/G3D/Array.h b/dep/g3dlite/include/G3D/Array.h
index cc9e1d9dd01..c562f5c920f 100644
--- a/dep/g3dlite/include/G3D/Array.h
+++ b/dep/g3dlite/include/G3D/Array.h
@@ -1,13 +1,13 @@
/**
- @file Array.h
+ \file Array.h
- @maintainer Morgan McGuire, graphics3d.com
- @cite Portions written by Aaron Orenstein, a@orenstein.name
+ \maintainer Morgan McGuire, graphics3d.com
+ \cite Portions written by Aaron Orenstein, a@orenstein.name
- @created 2001-03-11
- @edited 2009-05-29
+ \created 2001-03-11
+ \edited 2013-01-28
- Copyright 2000-2009, Morgan McGuire, http://graphics.cs.williams.edu
+ Copyright 2000-2012, Morgan McGuire, http://graphics.cs.williams.edu
All rights reserved.
*/
@@ -16,8 +16,8 @@
#include "G3D/platform.h"
#include "G3D/debug.h"
-#include "G3D/System.h"
#include "G3D/MemoryManager.h"
+#include "G3D/System.h"
#ifdef G3D_DEBUG
// For formatting error messages
# include "G3D/format.h"
@@ -47,6 +47,8 @@ const int SORT_INCREASING = 1;
/** Constant for Array::sort */
const int SORT_DECREASING = -1;
+
+
/**
\brief Dynamic 1D array tuned for performance.
@@ -89,22 +91,26 @@ const int SORT_DECREASING = -1;
\sa G3D::SmallArray
*/
-template <class T, int MIN_ELEMENTS = 10, size_t MIN_BYTES = 32>
+template <class T, size_t MIN_ELEMENTS = 10>
class Array {
+
private:
+ /** Once the array has been allocated, it will never deallocate the underlying
+ array unless MIN_ELEMENTS is set to 0, MIN_BYTES is 0, and the array is empty. */
+ static const size_t MIN_BYTES = 32;
+
/** 0...num-1 are initialized elements, num...numAllocated-1 are not */
T* data;
- int num;
- int numAllocated;
+ size_t num;
+ size_t numAllocated;
MemoryManager::Ref m_memoryManager;
/** \param n Number of elements
*/
- void init(int n, const MemoryManager::Ref& m) {
+ void init(size_t n, const MemoryManager::Ref& m) {
m_memoryManager = m;
- debugAssert(n >= 0);
this->num = 0;
this->numAllocated = 0;
data = NULL;
@@ -117,7 +123,7 @@ private:
void _copy(const Array &other) {
init(other.num, MemoryManager::create());
- for (int i = 0; i < num; i++) {
+ for (size_t i = 0; i < num; ++i) {
data[i] = other.data[i];
}
}
@@ -142,7 +148,7 @@ private:
and then copies at most oldNum elements from the old array to it. Destructors are
called for oldNum elements of the old array.
*/
- void realloc(int oldNum) {
+ void realloc(size_t oldNum) {
T* oldData = data;
// The allocation is separate from the constructor invocation because we don't want
@@ -154,7 +160,7 @@ private:
alwaysAssertM(data, "Memory manager returned NULL: out of memory?");
// Call the copy constructors
- {const int N = G3D::min(oldNum, numAllocated);
+ {const size_t N = G3D::min(oldNum, numAllocated);
const T* end = data + N;
T* oldPtr = oldData;
for (T* ptr = data; ptr < end; ++ptr, ++oldPtr) {
@@ -178,6 +184,27 @@ private:
}
public:
+ /**
+ Assignment operator. Will be private in a future release because this is slow and can be invoked by accident by novice C++ programmers.
+ If you really want to copy an Array, use the explicit copy constructor.
+ */
+ Array& operator=(const Array& other) {
+ resize(other.num);
+ for (int i = 0; i < (int)num; ++i) {
+ data[i] = other[i];
+ }
+ return *this;
+ }
+
+ Array& operator=(const std::vector<T>& other) {
+ resize(other.size());
+ for (size_t i = 0; i < num; ++i) {
+ data[i] = other[i];
+ }
+ return *this;
+ }
+
+public:
/**
G3D C++ STL style iterator variable. Call begin() to get
@@ -211,7 +238,7 @@ public:
return data;
}
/**
- C++ STL style iterator method. Returns one after the last iterator
+ C++ STL style iterator method. Returns one after the last valid iterator
element.
*/
ConstIterator end() const {
@@ -224,15 +251,27 @@ public:
/**
The array returned is only valid until the next append() or resize call, or
- the Array is deallocated.
+ the Array is deallocated.
*/
T* getCArray() {
return data;
}
+ /** Exchanges all data between the two arrays, which are required to have a common MemoryManager.
+ This is a convenient
+ way to avoid large array copies when handing off data without involving reference counting
+ or manual memory management. Beware that pointers or references into the arrays will
+ access memory in the <i>other</i> array after the swap. */
+ static void swap(Array<T, MIN_ELEMENTS>& a, Array<T, MIN_ELEMENTS>& b) {
+ alwaysAssertM(a.memoryManager() == b.memoryManager(), "The arrays are required to have the same memory manager");
+ std::swap(a.data, b.data);
+ std::swap(a.num, b.num);
+ std::swap(a.numAllocated, b.numAllocated);
+ }
+
/**
The array returned is only valid until the next append() or resize call, or
- the Array is deallocated.
+ the Array is deallocated.
*/
const T* getCArray() const {
return data;
@@ -241,12 +280,11 @@ public:
/** Creates a zero length array (no heap allocation occurs until resize). */
Array() : num(0) {
init(0, MemoryManager::create());
- debugAssert(num >= 0);
}
/** Creates an array containing v0. */
- Array(const T& v0) {
+ explicit Array(const T& v0) {
init(1, MemoryManager::create());
(*this)[0] = v0;
}
@@ -287,11 +325,58 @@ public:
/**
- Copy constructor
+ Copy constructor. Copying arrays is slow...perhaps you want to pass a reference or a pointer instead?
*/
- Array(const Array& other) : num(0) {
+ //TODO: patch rest of the API to prevent returning Arrays by value, then make explicit
+ Array(const Array& other) : num(0) {
_copy(other);
- debugAssert(num >= 0);
+ }
+
+ explicit Array(const std::vector<T>& other) : num(0), data(NULL) {
+ *this = other;
+ }
+
+
+ /* Sets this to hold the same contents as other, with num = numAllocated (no unused allocated space) */
+ void copyFrom(const Array<T>& other) {
+ resize(0);
+ append(other);
+ }
+
+
+ /** Resizes this to match the size of \a other and then copies the data from other using memcpy. This is only safe for POD types */
+ void copyPOD(const Array<T>& other) {
+ if (numAllocated < other.num) {
+ m_memoryManager->free(data);
+ data = NULL;
+ if (other.data) {
+ data = (T*)m_memoryManager->alloc(sizeof(T) * other.num);
+ }
+ numAllocated = other.num;
+ }
+
+ num = other.num;
+ if (other.data && (num > 0)) {
+ System::memcpy(data, other.data, sizeof(T) * num);
+ }
+ }
+
+ /** Resizes this to just barely match the size of \a other + itself and then copies the data to the end of the array from other using memcpy.
+ This is only safe for POD types */
+ void appendPOD(const Array<T>& other) {
+ const size_t oldSize = num;
+ num += other.num;
+ if (numAllocated < num) {
+ alwaysAssertM(other.data, "non-zero array with no allocated space");
+ T* old = data;
+ data = (T*)m_memoryManager->alloc(sizeof(T) * num);
+ System::memcpy(data, old, sizeof(T) * oldSize);
+ m_memoryManager->free(old);
+ numAllocated = num;
+ }
+ if (other.data) {
+ System::memcpy((data + oldSize), other.data, sizeof(T) * other.num);
+ }
}
/**
@@ -303,14 +388,14 @@ public:
*/
~Array() {
// Invoke the destructors on the elements
- for (int i = 0; i < num; i++) {
+ for (size_t i = 0; i < num; ++i) {
(data + i)->~T();
}
m_memoryManager->free(data);
// Set to 0 in case this Array is global and gets referenced during app exit
data = NULL;
- num = 0;
+ num = 0;
numAllocated = 0;
}
@@ -335,26 +420,6 @@ public:
clear(false);
}
- /**
- Assignment operator.
- */
- Array& operator=(const Array& other) {
- debugAssert(num >= 0);
- resize(other.num); for (int i = 0; i < num; ++i) {
- data[i] = other[i];
- }
- debugAssert(num >= 0);
- return *this;
- }
-
- Array& operator=(const std::vector<T>& other) {
- resize((int)other.size());
- for (int i = 0; i < num; ++i) {
- data[i] = other[i];
- }
- return *this;
- }
-
inline MemoryManager::Ref memoryManager() const {
return m_memoryManager;
}
@@ -363,7 +428,7 @@ public:
Number of elements in the array.
*/
inline int size() const {
- return num;
+ return (int)num;
}
/**
@@ -379,8 +444,7 @@ public:
shrinks the array by one.
*/
void fastRemove(int index, bool shrinkIfNecessary = false) {
- debugAssert(index >= 0);
- debugAssert(index < num);
+ debugAssert(index < (int)num);
data[index] = data[num - 1];
resize(size() - 1, shrinkIfNecessary);
}
@@ -393,32 +457,52 @@ public:
// Add space for the extra element
resize(num + 1, false);
- for (int i = num - 1; i > n; --i) {
+ for (size_t i = (size_t)(num - 1); i > (size_t)n; --i) {
data[i] = data[i - 1];
}
data[n] = value;
}
+ /** Sets all elements currently in the array to \param value */
+ void setAll(const T& value) {
+ for (size_t i = 0; i < num; ++i) {
+ data[i] = value;
+ }
+ }
+
+ /** Resize this array to consume exactly the capacity required by its size.
+ \sa clear, resize, capacity, size
+ */
+ void trimToSize() {
+ if (size() != capacity()) {
+ size_t oldNum = numAllocated;
+ numAllocated = size();
+ realloc(oldNum);
+ }
+ }
+
/** @param shrinkIfNecessary if false, memory will never be
reallocated when the array shrinks. This makes resizing much
- faster but can waste memory.
+ faster but can waste memory. Default = true.
+
+ \sa clear, trimToSize
*/
- void resize(int n, bool shrinkIfNecessary = true) {
- debugAssert(n >= 0);
+ void resize(size_t n, bool shrinkIfNecessary = true) {
+ alwaysAssertM(n < 0xFFFFFFFF, "This implementation does not support arrays with more than 2^32 elements, although the size in memory may be larger.");
if (num == n) {
return;
}
- int oldNum = num;
+ size_t oldNum = num;
num = n;
// Call the destructors on newly hidden elements if there are any
- for (int i = num; i < oldNum; ++i) {
+ for (size_t i = num; i < oldNum; ++i) {
(data + i)->~T();
}
// Once allocated, always maintain MIN_ELEMENTS elements or 32 bytes, whichever is higher.
- const int minSize = std::max(MIN_ELEMENTS, (int)(MIN_BYTES / sizeof(T)));
+ const size_t minSize = G3D::max(MIN_ELEMENTS, (size_t)(MIN_BYTES / sizeof(T)));
if ((MIN_ELEMENTS == 0) && (MIN_BYTES == 0) && (n == 0) && shrinkIfNecessary) {
// Deallocate the array completely
@@ -450,18 +534,21 @@ public:
//
// These numbers are tweaked according to performance tests.
- float growFactor = 3.0;
+ double growFactor = 3.0f;
- int oldSizeBytes = numAllocated * sizeof(T);
- if (oldSizeBytes > 400000) {
- // Avoid bloat
- growFactor = 1.5;
+ size_t oldSizeBytes = numAllocated * sizeof(T);
+ if (oldSizeBytes > 10000000) {
+ // Conserve memory more tightly above 10 MB
+ growFactor = 1.2f;
+ } else if (oldSizeBytes > 400000) {
+ // Avoid bloat above 400k
+ growFactor = 1.5f;
} else if (oldSizeBytes > 64000) {
// This is what std:: uses at all times
- growFactor = 2.0;
+ growFactor = 2.0f;
}
- numAllocated = (num - numAllocated) + (int)(numAllocated * growFactor);
+ numAllocated = (num - numAllocated) + (size_t)(numAllocated * growFactor);
if (numAllocated < minSize) {
numAllocated = minSize;
@@ -476,14 +563,14 @@ public:
// Only copy over old elements that still remain after resizing
// (destructors were called for others if we're shrinking)
- realloc(iMin(num, oldNum));
+ realloc(min(num, oldNum));
}
// Call the constructors on newly revealed elements.
// Do not use parens because we don't want the intializer
// invoked for POD types.
- for (int i = oldNum; i < num; ++i) {
+ for (size_t i = oldNum; i < num; ++i) {
new (data + i) T;
}
}
@@ -583,6 +670,62 @@ public:
}
}
+ void append(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5) {
+ if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4) || inArray(&v5)) {
+ T t1 = v1;
+ T t2 = v2;
+ T t3 = v3;
+ T t4 = v4;
+ T t5 = v5;
+ append(t1, t2, t3, t4, t5);
+ } else if (num + 4 < numAllocated) {
+ // This is a simple situation; just stick it in the next free slot using
+ // the copy constructor.
+ new (data + num) T(v1);
+ new (data + num + 1) T(v2);
+ new (data + num + 2) T(v3);
+ new (data + num + 3) T(v4);
+ new (data + num + 4) T(v5);
+ num += 5;
+ } else {
+ resize(num + 5, DONT_SHRINK_UNDERLYING_ARRAY);
+ data[num - 5] = v1;
+ data[num - 4] = v2;
+ data[num - 3] = v3;
+ data[num - 2] = v4;
+ data[num - 1] = v5;
+ }
+ }
+
+ void append(const T& v1, const T& v2, const T& v3, const T& v4, const T& v5, const T& v6) {
+ if (inArray(&v1) || inArray(&v2) || inArray(&v3) || inArray(&v4) || inArray(&v5) || inArray(&v6)) {
+ T t1 = v1;
+ T t2 = v2;
+ T t3 = v3;
+ T t4 = v4;
+ T t5 = v5;
+ T t6 = v6;
+ append(t1, t2, t3, t4, t5, t6);
+ } else if (num + 5 < numAllocated) {
+ // This is a simple situation; just stick it in the next free slot using
+ // the copy constructor.
+ new (data + num) T(v1);
+ new (data + num + 1) T(v2);
+ new (data + num + 2) T(v3);
+ new (data + num + 3) T(v4);
+ new (data + num + 4) T(v5);
+ new (data + num + 5) T(v6);
+ num += 6;
+ } else {
+ resize(num + 6, DONT_SHRINK_UNDERLYING_ARRAY);
+ data[num - 6] = v1;
+ data[num - 5] = v2;
+ data[num - 4] = v3;
+ data[num - 3] = v4;
+ data[num - 2] = v5;
+ data[num - 1] = v6;
+ }
+ }
/**
Returns true if the given element is in the array.
*/
@@ -602,12 +745,12 @@ public:
*/
void append(const Array<T>& array) {
debugAssert(this != &array);
- int oldNum = num;
- int arrayLength = array.length();
+ size_t oldNum = num;
+ size_t arrayLength = array.length();
resize(num + arrayLength, false);
- for (int i = 0; i < arrayLength; i++) {
+ for (size_t i = 0; i < arrayLength; ++i) {
data[oldNum + i] = array.data[i];
}
}
@@ -648,8 +791,8 @@ public:
sequence, a value at least as large as size()"
For compatibility with std::vector.
*/
- int capacity() const {
- return numAllocated;
+ int capacity() const {
+ return (int)numAllocated;
}
/**
@@ -723,27 +866,40 @@ public:
Performs bounds checks in debug mode
*/
inline T& operator[](int n) {
- debugAssertM((n >= 0) && (n < num), format("Array index out of bounds. n = %d, size() = %d", n, num));
+ debugAssertM((n >= 0) && (n < (int)num),
+ format("Array index out of bounds. n = %d, size() = %d", (int)n, (int)num));
debugAssert(data!=NULL);
return data[n];
}
- inline T& operator[](unsigned int n) {
- debugAssertM(n < (unsigned int)num, format("Array index out of bounds. n = %d, size() = %d", n, num));
- return data[n];
+ inline T& operator[](uint32 n) {
+ debugAssertM(n < (uint32)num, format("Array index out of bounds. n = %d, size() = %d",
+ (int)n, (int)num));
+ return data[n];
+ }
+
+ inline T& operator[](uint64 n) {
+ debugAssertM(n < (uint64)num, format("Array index out of bounds. n = %d, size() = %d", (int)n, (int)num));
+ return data[n];
}
/**
Performs bounds checks in debug mode
*/
inline const T& operator[](int n) const {
- debugAssert((n >= 0) && (n < num));
+ debugAssert((n >= 0) && (n < (int)num));
+ debugAssert(data != NULL);
+ return data[n];
+ }
+
+ inline const T& operator[](uint32 n) const {
+ debugAssert((n < (uint32)num));
debugAssert(data!=NULL);
return data[n];
}
- inline const T& operator[](unsigned int n) const {
- debugAssert((n < (unsigned int)num));
+ inline const T& operator[](uint64 n) const {
+ debugAssert((n < (uint64)num));
debugAssert(data!=NULL);
return data[n];
}
@@ -751,7 +907,7 @@ public:
inline T& randomElement() {
debugAssert(num > 0);
debugAssert(data!=NULL);
- return data[iRandom(0, num - 1)];
+ return data[iRandom(0, (int)num - 1)];
}
inline const T& randomElement() const {
@@ -821,13 +977,18 @@ public:
Calls delete on all objects[0...size-1]
and sets the size to zero.
*/
- void deleteAll() {
- for (int i = 0; i < num; i++) {
+ void invokeDeleteOnAllElements() {
+ for (size_t i = 0; i < num; ++i) {
delete data[i];
}
resize(0);
}
+ /** \deprecated */
+ void G3D_DEPRECATED deleteAll() {
+ invokeDeleteOnAllElements();
+ }
+
/**
Returns the index of (the first occurance of) an index or -1 if
not found. Searches from the right.
@@ -846,9 +1007,9 @@ public:
not found.
*/
int findIndex(const T& value) const {
- for (int i = 0; i < num; ++i) {
+ for (size_t i = 0; i < num; ++i) {
if (data[i] == value) {
- return i;
+ return (int)i;
}
}
return -1;
@@ -894,8 +1055,8 @@ public:
}
void remove(int index, int count = 1) {
- debugAssert((index >= 0) && (index < num));
- debugAssert((count > 0) && (index + count <= num));
+ debugAssert((index >= 0) && (index < (int)num));
+ debugAssert((count > 0) && (index + count <= (int)num));
remove(begin() + index, count);
}
@@ -906,8 +1067,8 @@ public:
void reverse() {
T temp;
- int n2 = num / 2;
- for (int i = 0; i < n2; ++i) {
+ size_t n2 = num / 2;
+ for (size_t i = 0; i < n2; ++i) {
temp = data[num - 1 - i];
data[num - 1 - i] = data[i];
data[i] = temp;
@@ -917,29 +1078,29 @@ public:
/**
Sort using a specific less-than function, e.g.:
- <PRE>
+ \code
bool __cdecl myLT(const MyClass& elem1, const MyClass& elem2) {
return elem1.x < elem2.x;
}
- </PRE>
+ \endcode
Note that for pointer arrays, the <CODE>const</CODE> must come
<I>after</I> the class name, e.g., <CODE>Array<MyClass*></CODE> uses:
- <PRE>
+ \code
bool __cdecl myLT(MyClass*const& elem1, MyClass*const& elem2) {
return elem1->x < elem2->x;
}
- </PRE>
+ \endcode
or a functor, e.g.,
- <pre>
+ \code
bool
less_than_functor::operator()( const double& lhs, const double& rhs ) const
{
return( lhs < rhs? true : false );
}
-</pre>
+\endcode
*/
// void sort(bool (__cdecl *lessThan)(const T& elem1, const T& elem2)) {
// std::sort(data, data + num, lessThan);
@@ -955,14 +1116,14 @@ return( lhs < rhs? true : false );
Sorts the array in increasing order using the > or < operator. To
invoke this method on Array<T>, T must override those operator.
You can overide these operators as follows:
- <code>
+ \code
bool T::operator>(const T& other) const {
return ...;
}
bool T::operator<(const T& other) const {
return ...;
}
- </code>
+ \endcode
*/
void sort(int direction = SORT_INCREASING) {
if (direction == SORT_INCREASING) {
@@ -1053,7 +1214,7 @@ return( lhs < rhs? true : false );
// Form a table of buckets for lt, eq, and gt
Array<T>* bucket[3] = {&ltArray, &eqArray, &gtArray};
- for (int i = 0; i < num; ++i) {
+ for (size_t i = 0; i < num; ++i) {
int c = comparator(partitionElement, data[i]);
debugAssertM(c >= -1 && c <= 1, "Comparator returned an illegal value.");
@@ -1236,6 +1397,8 @@ return( lhs < rhs? true : false );
medianPartition(ltMedian, eqMedian, gtMedian, temp, DefaultComparator());
}
+
+
/** Redistributes the elements so that the new order is statistically independent
of the original order. O(n) time.*/
@@ -1252,6 +1415,35 @@ return( lhs < rhs? true : false );
}
+ /** Ensures that future append() calls can grow up to size \a n without allocating memory.*/
+ void reserve(int n) {
+ debugAssert(n >= size());
+ const int oldSize = size();
+ resize(n);
+ resize(oldSize, false);
+ }
+
+ /** Number of bytes used by the array object and the memory allocated for it's data pointer. Does *not*
+ * include the memory of objects pointed to by objects in the data array */
+ size_t sizeInMemory() const {
+ return sizeof(Array<T>) + (sizeof(T) * numAllocated);
+ }
+
+ /** Remove all NULL elements in linear time without affecting order of the other elements. */
+ void removeNulls() {
+ int nextNull = 0;
+ for (int i = 0; i < size(); ++i) {
+ if (notNull(data[i])) {
+ if (i > nextNull) {
+ // Move value i down to squeeze out NULLs
+ data[nextNull] = data[i];
+ }
+ ++nextNull;
+ }
+ }
+
+ resize(nextNull, false);
+ }
};
diff --git a/dep/g3dlite/include/G3D/AtomicInt32.h b/dep/g3dlite/include/G3D/AtomicInt32.h
index 2d63f998355..7b56e001ae2 100644
--- a/dep/g3dlite/include/G3D/AtomicInt32.h
+++ b/dep/g3dlite/include/G3D/AtomicInt32.h
@@ -28,7 +28,7 @@ namespace G3D {
*/
class AtomicInt32 {
private:
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
volatile long m_value;
# elif defined(G3D_OSX)
int32_t m_value;
@@ -70,7 +70,7 @@ public:
/** Returns the old value, before the add. */
int32 add(const int32 x) {
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
return InterlockedExchangeAdd(&m_value, x);
@@ -98,7 +98,7 @@ public:
}
void increment() {
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
// Note: returns the newly incremented value
InterlockedIncrement(&m_value);
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
@@ -111,7 +111,7 @@ public:
/** Returns zero if the result is zero after decrement, non-zero otherwise.*/
int32 decrement() {
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
// Note: returns the newly decremented value
return InterlockedDecrement(&m_value);
# elif defined(G3D_LINUX) || defined(G3D_FREEBSD)
@@ -140,7 +140,7 @@ public:
Under VC6 the sign bit may be lost.
*/
int32 compareAndSet(const int32 comperand, const int32 exchange) {
-# if defined(G3D_WIN32)
+# 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
diff --git a/dep/g3dlite/include/G3D/BIN.h b/dep/g3dlite/include/G3D/BIN.h
new file mode 100644
index 00000000000..e4c86768dea
--- /dev/null
+++ b/dep/g3dlite/include/G3D/BIN.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/BinaryInput.h b/dep/g3dlite/include/G3D/BinaryInput.h
index e8a9b88618b..e8335c6812c 100644
--- a/dep/g3dlite/include/G3D/BinaryInput.h
+++ b/dep/g3dlite/include/G3D/BinaryInput.h
@@ -1,12 +1,12 @@
/**
- @file BinaryInput.h
+ \file G3D/BinaryInput.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-09
- @edited 2010-03-19
+ \created 2001-08-09
+ \edited 2013-01-03
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -26,6 +26,7 @@
#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"
@@ -39,7 +40,7 @@
namespace G3D {
-#if defined(G3D_WIN32) || defined(G3D_LINUX)
+#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
@@ -69,8 +70,15 @@ class BinaryInput {
private:
// The initial buffer will be no larger than this, but
- // may grow if a large memory read occurs. 50 MB
- enum {INITIAL_BUFFER_LENGTH = 50000000};
+ // 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
@@ -94,6 +102,7 @@ private:
/** 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;
@@ -122,14 +131,8 @@ private:
void loadIntoMemory(int64 startPosition, int64 minLength = 0);
/** Verifies that at least this number of bytes can be read.*/
- inline void prepareToRead(int64 nbytes) {
- debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
- debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
+ void prepareToRead(int64 nbytes);
- if (m_pos + nbytes > m_bufferLength) {
- loadIntoMemory(m_pos + m_alreadyRead, nbytes);
- }
- }
// Not implemented on purpose, don't use
BinaryInput(const BinaryInput&);
@@ -165,6 +168,7 @@ public:
To decompress part of a file, you can follow the following paradigm:
+ \htmlonly
<PRE>
BinaryInput master(...);
@@ -176,6 +180,7 @@ public:
// Now read from subset (it is ok for master to go out of scope)
</PRE>
+ \endhtmlonly
*/
BinaryInput(
const uint8* data,
@@ -200,23 +205,12 @@ public:
}
/**
- Returns a pointer to the internal memory buffer.
- May throw an exception for huge files.
- */
- const uint8* getCArray() const {
- if (m_alreadyRead > 0) {
- throw "Cannot getCArray for a huge file";
- }
- return m_buffer;
- }
-
- /**
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)
*/
- inline uint8 operator[](int64 n) {
+ uint8 operator[](int64 n) {
setPosition(n);
return readUInt8();
}
@@ -224,11 +218,11 @@ public:
/**
Returns the length of the file in bytes.
*/
- inline int64 getLength() const {
+ int64 getLength() const {
return m_length;
}
- inline int64 size() const {
+ int64 size() const {
return getLength();
}
@@ -236,15 +230,26 @@ public:
Returns the current byte position in the file,
where 0 is the beginning and getLength() - 1 is the end.
*/
- inline int64 getPosition() const {
+ 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.
*/
- inline void setPosition(int64 p) {
+ 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)) {
@@ -255,25 +260,31 @@ public:
/**
Goes back to the beginning of the file.
*/
- inline void reset() {
+ void reset() {
setPosition(0);
}
- inline int8 readInt8() {
+ void readBytes(void* bytes, int64 n);
+
+ int8 readInt8() {
prepareToRead(1);
return m_buffer[m_pos++];
}
-
- inline bool readBool8() {
+
+ bool readBool8() {
return (readInt8() != 0);
}
-
- inline uint8 readUInt8() {
+
+ uint8 readUInt8() {
prepareToRead(1);
return ((uint8*)m_buffer)[m_pos++];
}
+
+ unorm8 readUNorm8() {
+ return unorm8::fromBits(readUInt8());
+ }
- uint16 inline readUInt16() {
+ uint16 readUInt16() {
prepareToRead(2);
m_pos += 2;
@@ -295,12 +306,12 @@ public:
}
- inline int16 readInt16() {
+ int16 readInt16() {
uint16 a = readUInt16();
return *(int16*)&a;
}
- inline uint32 readUInt32() {
+ uint32 readUInt32() {
prepareToRead(4);
m_pos += 4;
@@ -326,19 +337,19 @@ public:
}
- inline int32 readInt32() {
+ int32 readInt32() {
uint32 a = readUInt32();
return *(int32*)&a;
}
uint64 readUInt64();
- inline int64 readInt64() {
+ int64 readInt64() {
uint64 a = readUInt64();
return *(int64*)&a;
}
- inline float32 readFloat32() {
+ float32 readFloat32() {
union {
uint32 a;
float32 b;
@@ -347,7 +358,7 @@ public:
return b;
}
- inline float64 readFloat64() {
+ float64 readFloat64() {
union {
uint64 a;
float64 b;
@@ -356,31 +367,34 @@ public:
return b;
}
- void readBytes(void* bytes, int64 n);
-
/**
- Reads an n character string. The string is not
- required to end in NULL in the file but will
- always be a proper std::string when returned.
+ Always consumes \a maxLength characters. Reads a string until NULL or \a maxLength characters. Does not require NULL termination.
*/
- std::string readString(int64 n);
+ std::string readString(int64 maxLength);
/**
- Reads until NULL or the end of the file is encountered.
+ Reads a string until NULL or end of file.
*/
std::string readString();
- /** Reads until \r, \r\n, \n\r, \n or the end of the file is encountered. Consumes the newline.*/
+ /** 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 ("&#92;r", "&#92;n", "&#92;r&#92;n", "&#92;n&#92;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.
+ 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();
@@ -393,15 +407,15 @@ public:
/**
Skips ahead n bytes.
*/
- inline void skip(int64 n) {
+ void skip(int64 n) {
setPosition(m_pos + m_alreadyRead + n);
}
/**
Returns true if the position is not at the end of the file
*/
- inline bool hasMore() const {
- return m_pos + m_alreadyRead < m_length;
+ bool hasMore() const {
+ return m_pos + m_alreadyRead < m_length;
}
/** Prepares for bit reading via readBits. Only readBits can be
diff --git a/dep/g3dlite/include/G3D/BinaryOutput.h b/dep/g3dlite/include/G3D/BinaryOutput.h
index d81ec56a67b..45e1124d7b4 100644
--- a/dep/g3dlite/include/G3D/BinaryOutput.h
+++ b/dep/g3dlite/include/G3D/BinaryOutput.h
@@ -1,17 +1,17 @@
/**
- @file BinaryOutput.h
+ \file G3D/BinaryOutput.h
- @maintainer Morgan McGuire, graphics3d.com
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-09
- @edited 2008-01-24
+ \created 2001-08-09
+ \edited 2011-08-24
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_BINARYOUTPUT_H
-#define G3D_BINARYOUTPUT_H
+#ifndef G3D_BinaryOutput_h
+#define G3D_BinaryOutput_h
#include "G3D/platform.h"
#include <assert.h>
@@ -19,6 +19,7 @@
#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"
@@ -73,19 +74,19 @@ private:
uint8* m_buffer;
/** Size of the elements used */
- int m_bufferLen;
+ size_t m_bufferLen;
/** Underlying size of memory allocaded */
- int m_maxBufferLen;
+ size_t m_maxBufferLen;
/** Next byte in file */
- int m_pos;
+ int64 m_pos;
/** is this initialized? */
bool m_init;
- /** Number of bytes already written to the file.*/
- size_t m_alreadyWritten;
+ /** Number of bytes already written to the file. Even on 32-bit OS, this can be 64-bits*/
+ int64 m_alreadyWritten;
bool m_ok;
@@ -97,11 +98,11 @@ private:
Make sure at least bytes can be written, resizing if
necessary.
*/
- inline void reserveBytes(int bytes) {
+ inline void reserveBytes(size_t bytes) {
debugAssert(bytes > 0);
- size_t oldBufferLen = (size_t)m_bufferLen;
+ size_t oldBufferLen = m_bufferLen;
- m_bufferLen = iMax(m_bufferLen, (m_pos + bytes));
+ m_bufferLen = max(m_bufferLen, (size_t)(m_pos + bytes));
if (m_bufferLen > m_maxBufferLen) {
reallocBuffer(bytes, oldBufferLen);
}
@@ -138,8 +139,10 @@ public:
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();
+ void compress(int level = 9);
/** True if no errors have been encountered.*/
bool ok() const;
@@ -190,11 +193,11 @@ public:
void reset();
- inline int length() const {
- return (int)m_bufferLen + (int)m_alreadyWritten;
+ inline int64 length() const {
+ return m_bufferLen + m_alreadyWritten;
}
- inline int size() const {
+ inline int64 size() const {
return length();
}
@@ -207,18 +210,18 @@ public:
Throws char* when resetting a huge file to be shorter
than its current length.
*/
- inline void setLength(int n) {
- n = n - (int)m_alreadyWritten;
+ inline void setLength(int64 n) {
+ n = n - m_alreadyWritten;
if (n < 0) {
throw "Cannot resize huge files to be shorter.";
}
- if (n < m_bufferLen) {
+ if (n < (int64)m_bufferLen) {
m_pos = n;
}
- if (n > m_bufferLen) {
- reserveBytes(n - m_bufferLen);
+ if (n > (int64)m_bufferLen) {
+ reserveBytes((size_t)(n - m_bufferLen));
}
}
@@ -227,7 +230,7 @@ public:
where 0 is the beginning and getLength() - 1 is the end.
*/
inline int64 position() const {
- return (int64)m_pos + (int64)m_alreadyWritten;
+ return m_pos + m_alreadyWritten;
}
@@ -239,9 +242,9 @@ public:
May throw a char* exception when seeking backwards on a huge file.
*/
inline void setPosition(int64 p) {
- p = p - (int64)m_alreadyWritten;
+ p = p - m_alreadyWritten;
- if (p > m_bufferLen) {
+ if (p > (int64)m_bufferLen) {
setLength((int)(p + (int64)m_alreadyWritten));
}
@@ -253,9 +256,9 @@ public:
}
- void writeBytes(
- const void* b,
- int count) {
+ void writeBytes
+ (const void* b,
+ size_t count) {
reserveBytes(count);
debugAssert(m_pos >= 0);
@@ -270,7 +273,7 @@ public:
inline void writeInt8(int8 i) {
reserveBytes(1);
m_buffer[m_pos] = *(uint8*)&i;
- m_pos++;
+ ++m_pos;
}
inline void writeBool8(bool b) {
@@ -280,7 +283,11 @@ public:
inline void writeUInt8(uint8 i) {
reserveBytes(1);
m_buffer[m_pos] = i;
- m_pos++;
+ ++m_pos;
+ }
+
+ inline void writeUNorm8(unorm8 i) {
+ writeUInt8(i.bits());
}
void writeUInt16(uint16 u);
@@ -328,6 +335,20 @@ public:
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);
/**
@@ -340,12 +361,11 @@ public:
void writeStringEven(const char* s);
-
void writeString32(const char* s);
/**
- Write a string with a 32-bit length field in front
- of it.
+ 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());
@@ -365,8 +385,8 @@ public:
Skips ahead n bytes.
*/
inline void skip(int n) {
- if (m_pos + n > m_bufferLen) {
- setLength((int)m_pos + (int)m_alreadyWritten + n);
+ if (m_pos + n > (int64)m_bufferLen) {
+ setLength(m_pos + m_alreadyWritten + n);
}
m_pos += n;
}
diff --git a/dep/g3dlite/include/G3D/Box.h b/dep/g3dlite/include/G3D/Box.h
index 82af9125b05..5409af803b6 100644
--- a/dep/g3dlite/include/G3D/Box.h
+++ b/dep/g3dlite/include/G3D/Box.h
@@ -1,20 +1,20 @@
/**
- @file Box.h
+ \file G3D/Box.h
Box class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \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 2007-06-05
+ \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-2006, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_BOX_H
-#define G3D_BOX_H
+#ifndef G3D_Box_h
+#define G3D_Box_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -24,13 +24,12 @@
namespace G3D {
class CoordinateFrame;
+class Any;
/**
- An arbitrary 3D box, useful as a bounding box.
-
-
- To construct a box from a coordinate frame, center and extent, use the idiom:
+ \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 {
@@ -41,29 +40,14 @@ private:
friend class CoordinateFrame;
/**
- <PRE>
- 3 2 7 6
-
- 0 1 4 5
-
- front back (seen through front)
- </PRE>
- */
- Vector3 _corner[8];
-
- /**
- Unit axes.
+ Axes with length equal to the 4 edges that run along each of them
*/
- Vector3 _axis[3];
+ Vector3 _edgeVector[3];
- Vector3 _center;
-
- /**
- Extent along each axis.
- */
- Vector3 _extent;
+ Point3 _center;
float _area;
+
float _volume;
void init(
@@ -72,38 +56,47 @@ private:
public:
- /**
- Does not initialize the fields.
- */
Box();
+ explicit Box(const Any& a);
+
/**
Constructs a box from two opposite corners.
*/
- Box(
- const Vector3& min,
+ Box(const Vector3& min,
const Vector3& max);
- static Box inf();
+ Box(const Vector3& osMin,
+ const Vector3& osMax,
+ const CoordinateFrame& frame);
- Box(class BinaryInput& b);
+ Box(class BinaryInput& b);
Box(const class AABox& b);
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& 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. localFrame().worldToObject(...) takes
+ 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.
*/
@@ -111,18 +104,39 @@ public:
return _center;
}
+ /**
+ \htmlonly
+ <PRE>
+
+
+ 2--------3
+ / : /|
+ / : / |
+ 6--------7 |
+ | : | |
+ | 0....|..1
+ | / | /
+ |/ |/
+ 4--------5
+
+ y
+ ^
+ |
+ |-->x
+ z/
+
- inline Vector3 corner(int i) const {
- debugAssert(i < 8);
- return _corner[i];
- }
+ </PRE>
+ \endhtmlonly
+ */
+ Vector3 corner(int i) const;
/**
Unit length.
*/
inline Vector3 axis(int a) const {
debugAssert(a < 3);
- return _axis[a];
+ return _edgeVector[a].direction();
}
/**
@@ -131,17 +145,43 @@ public:
*/
inline float extent(int a) const {
debugAssert(a < 3);
- return (float)_extent[a];
+ return _edgeVector[a].length();
}
inline Vector3 extent() const {
- return _extent;
+ 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 counter clockwise quad facing outwards.
- */
+ 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,
@@ -150,24 +190,24 @@ public:
Vector3& v3) const;
- /**
+ /**
See AABox::culledBy
- */
+ */
bool culledBy
(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
- uint32& childMask) const;
+ 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;
+ const Array<Plane>& plane,
+ int32& cullingPlaneIndex = dummy,
+ const uint32 testMask = -1) const;
bool contains(
const Vector3& point) const;
diff --git a/dep/g3dlite/include/G3D/BumpMapPreprocess.h b/dep/g3dlite/include/G3D/BumpMapPreprocess.h
index 955f99e61b2..a2ddaf1901d 100644
--- a/dep/g3dlite/include/G3D/BumpMapPreprocess.h
+++ b/dep/g3dlite/include/G3D/BumpMapPreprocess.h
@@ -6,7 +6,7 @@
\created 2010-01-28
\edited 2010-01-28
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -20,7 +20,7 @@ class Any;
/**
Not in the BumpMap class to avoid a circular dependency between Texture and BumpMap.
-G3D::GImage::computeNormalMap().
+G3D::Image::computeNormalMap().
*/
class BumpMapPreprocess {
public:
@@ -46,7 +46,7 @@ public:
BumpMapPreprocess(const Any& any);
- operator Any() const;
+ Any toAny() const;
bool operator==(const BumpMapPreprocess& other) const {
return
diff --git a/dep/g3dlite/include/G3D/Capsule.h b/dep/g3dlite/include/G3D/Capsule.h
index baeea3aa82b..3f10743ccfe 100644
--- a/dep/g3dlite/include/G3D/Capsule.h
+++ b/dep/g3dlite/include/G3D/Capsule.h
@@ -26,32 +26,32 @@ class AABox;
*/
class Capsule {
private:
- Vector3 p1;
- Vector3 p2;
+ Vector3 p1;
+ Vector3 p2;
- float _radius;
+ 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;
- }
+ 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. */
diff --git a/dep/g3dlite/include/G3D/CollisionDetection.h b/dep/g3dlite/include/G3D/CollisionDetection.h
index c8fcf5534c2..906504ec5d9 100644
--- a/dep/g3dlite/include/G3D/CollisionDetection.h
+++ b/dep/g3dlite/include/G3D/CollisionDetection.h
@@ -1,5 +1,5 @@
/**
- @file CollisionDetection.h
+ \file CollisionDetection.h
Moving collision detection for simple primitives.
@@ -12,15 +12,15 @@
Thanks to Max McGuire of Iron Lore for various bug fixes.
Box-Triangle by Tomas Akenine-Moller
- @created 2001-11-19
- @edited 2008-12-19
+ \created 2001-11-19
+ \edited 2010-11-10
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_COLLISIONDETECTION_H
-#define G3D_COLLISIONDETECTION_H
+#ifndef G3D_CollisionDetection_h
+#define G3D_CollisionDetection_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -68,16 +68,17 @@ namespace G3D {
<b>Static Collision Detection:</b> (Neither object is moving)
<table>
- <tr><td></td><td><b>Vector3</b></td><td><b>LineSegment</b></td><td><b>Ray *</b></td><td><b>Line</b></td><td><b>Plane</b></td><td><b>Triangle</b></td><td><b>Sphere</b></td><td><b>Cylinder</b></td><td><b>Capsule</b></td><td><b>AABox</b></td><td><b>Box</b></td></tr>
- <tr><td><b>Vector3</b></td><td>\link Vector3::operator== V3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink</td><td bgcolor=#C0C0C0 colspan=10 ></td></tr>
+ <tr><td></td><td><b>Point3</b></td><td><b>LineSegment</b></td><td><b>Ray *</b></td><td><b>Line</b></td><td><b>Plane</b></td><td><b>Triangle</b></td><td><b>Sphere</b></td><td><b>Cylinder</b></td><td><b>Capsule</b></td><td><b>AABox</b></td><td><b>Box</b></td></tr>
+ <tr><td><b>Point3</b></td><td>\link Vector3::operator== P3::==\endlink \link Vector3::fuzzyEq V3::fuzzy \endlink \link G3D::distance distance \endlink</td><td bgcolor=#C0C0C0 colspan=10 ></td></tr>
<tr><td><b>LineSegment</b></td><td>\link LineSegment::closestPoint LS::closestPoint\endlink \link LineSegment::distance LS::distance\endlink \link CollisionDetection::closestPointOnLineSegment CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=9 ></td></tr>
<tr><td><b>Ray *</b></td><td>Ray::closestPoint Ray::distance</td><td></td><td></td><td bgcolor=#C0C0C0 colspan=8 ></td></tr>
<tr><td><b>Line</b></td><td>Line::closestPoint Line::distance</td><td></td><td>\link CollisionDetection::closestPointsBetweenLineAndLine CD\endlink</td><td></td><td bgcolor=#C0C0C0 colspan=7 ></td></tr>
<tr><td><b>Plane</b></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=6 ></td></tr>
<tr><td><b>Triangle</b></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=5 ></td></tr>
- <tr><td><b>Sphere</b></td><td>Sphere::contains</td><td></td><td>\link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=4 ></td></tr>
+ <tr><td><b>Sphere</b></td><td>Sphere::contains</td><td></td><td>\link CollisionDetection::collisionTimeForMovingPointFixedSphere CD \endlink, \link Ray::intersectionTime R::time\endlink</td><td></td><td></td><td>\link G3D::CollisionDetection::fixedSolidSphereIntersectsFixedTriangle CD\endlink</td><td>
+\link G3D::CollisionDetection::penetrationDepthForFixedSphereFixedSphere CD\endlink</td><td bgcolor=#C0C0C0 colspan=4 ></td></tr>
<tr><td><b>Cylinder</b></td><td>Cylinder::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=3 ></td></tr>
- <tr><td><b>Capsule</b></td><td>Capsule::contains</td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=2 ></td></tr>
+ <tr><td><b>Capsule</b></td><td>Capsule::contains</td> <td></td> <td></td> <td></td> <td></td> <td>\link G3D::CollisionDetection::collisionTimeForMovingSphereFixedTriangle CD\endlink</td> <td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=2 ></td></tr>
<tr><td><b>AABox</b></td><td>AABox::contains</td><td></td><td></td><td></td><td></td><td>\link CollisionDetection::fixedSolidBoxIntersectsFixedTriangle CD\endlink</td><td></td><td></td><td></td><td></td><td bgcolor=#C0C0C0 colspan=1 ></td></tr>
<tr><td><b>Box</b></td><td>Box::contains</td><td>(treat as Ray)</td><td>\link CollisionDetection::collisionTimeForMovingPointFixedBox CD\endlink</td><td>(treat as Ray)</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedPlane CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedSphereFixedBox CD\endlink</td><td>None (use OPCODE)</td><td>\link CollisionDetection::movingSpherePassesThroughFixedBox CD \endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td><td>\link CollisionDetection::penetrationDepthForFixedBoxFixedBox CD\endlink</td></tr>
</table>
@@ -88,30 +89,29 @@ namespace G3D {
<i>* Note: Moving collision detection against certain primitives is equivalent to static collision
detection against a bigger primitive. Ray, Line Segment == ``moving Point''; Capsule ==``moving Sphere''; Plane == ``moving Line''</i>
- @deprecated Routines moving to the G3D::Intersect class in G3D 8.0
+ @deprecated Routines moving to the G3D::Intersect class in G3D 9.0
*/
class CollisionDetection {
private:
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
- static Vector3 ignore;
-
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
+ /**
+ Default parameter if value passed to a function as reference is
+ not to be calculated. Must be explicitly supported by function.
+ */
+ static Vector3 ignore;
+
+ /**
+ Default parameter if value passed to a function as reference is
+ not to be calculated. Must be explicitly supported by function.
+ */
static bool ignoreBool;
- /**
- Default parameter if value passed to a function as reference is
- not to be calculated. Must be explicitly supported by function.
- */
+ /**
+ Default parameter if value passed to a function as reference is
+ not to be calculated. Must be explicitly supported by function.
+ */
static Array<Vector3> ignoreArray;
-
// Static class!
CollisionDetection() {}
virtual ~CollisionDetection() {}
@@ -123,32 +123,32 @@ public:
Does not return normalized vector in the edge-edge case
(indices 6 through 15).
- @param separatingAxisIndex Separating axis.
- @param box1 Box 1.
- @param box2 Box 2.
+ @param separatingAxisIndex Separating axis.
+ @param box1 Box 1.
+ @param box2 Box 2.
- @return Axis that separates the two boxes.
- */
+ @return Axis that separates the two boxes.
+ */
static Vector3 separatingAxisForSolidBoxSolidBox(
const int separatingAxisIndex,
const Box & box1,
const Box & box2);
/**
- Tests whether two boxes have axes that are parallel to
- each other. If they are, axis1 and axis2 are set to be
- the parallel axes for both box1 and box2 respectively.
-
- @param ca Dot products of each of the boxes axes
- @param epsilon Fudge factor (small unit by which the dot
- products may vary and still be considered
- zero).
- @param axis1 Parallel Axis 1. [Post Condition]
- @param axis2 Parallel Axis 2. [Post Condition]
-
- @return true - If boxes have a parallel axis
- @return false - otherwise.
- */
+ Tests whether two boxes have axes that are parallel to
+ each other. If they are, axis1 and axis2 are set to be
+ the parallel axes for both box1 and box2 respectively.
+
+ @param ca Dot products of each of the boxes axes
+ @param epsilon Fudge factor (small unit by which the dot
+ products may vary and still be considered
+ zero).
+ @param axis1 Parallel Axis 1. [Post Condition]
+ @param axis2 Parallel Axis 2. [Post Condition]
+
+ @return true - If boxes have a parallel axis
+ @return false - otherwise.
+ */
static bool parallelAxisForSolidBoxSolidBox(
const double* ca,
const double epsilon,
@@ -163,15 +163,15 @@ public:
penetrationDepthForFixedSphereFixedBox() for more details
@param separatingAxisIndex
- @param a Box 1's bounding sphere vector
- @param b Box 2's bounding sphere vector
- @param D Vector between Box 1 and Box 2's center points
- @param c Pointer to array of dot products of the axes of Box 1
- and Box 2.
- @param ca Pointer to array of unsigned dot products of the axes
- of Box 1 and Box 2.
- @param ad Pointer to array of dot products of Box 1 axes and D.
- @param bd Pointer to array of dot products of Box 2 axes and D.
+ @param a Box 1's bounding sphere vector
+ @param b Box 2's bounding sphere vector
+ @param D Vector between Box 1 and Box 2's center points
+ @param c Pointer to array of dot products of the axes of Box 1
+ and Box 2.
+ @param ca Pointer to array of unsigned dot products of the axes
+ of Box 1 and Box 2.
+ @param ad Pointer to array of dot products of Box 1 axes and D.
+ @param bd Pointer to array of dot products of Box 2 axes and D.
@return Projected distance between the two boxes along the
specified separating axis.
@@ -187,41 +187,41 @@ public:
const double* bd);
- /**
- Creates a set of standard information about two boxes in order to
- solve for their collision. This information includes a vector to
- the radius of the bounding sphere for each box, the vector between
- each boxes' center and a series of dot products between differing
- important vectors. These dot products include those between the axes
- of both boxes (signed and unsigned values), and the dot products
- between all the axes of box1 and the boxes' center vector and box2
- and the boxes' center vector.
-
- @pre The following space requirements must be met:
- - c[] 9 elements
- - ca[] 9 elements
- - ad[] 3 elements
- - bd[] 3 elements
-
- @cite dobted from David Eberly's papers, variables used in this function
+ /**
+ Creates a set of standard information about two boxes in order to
+ solve for their collision. This information includes a vector to
+ the radius of the bounding sphere for each box, the vector between
+ each boxes' center and a series of dot products between differing
+ important vectors. These dot products include those between the axes
+ of both boxes (signed and unsigned values), and the dot products
+ between all the axes of box1 and the boxes' center vector and box2
+ and the boxes' center vector.
+
+ @pre The following space requirements must be met:
+ - c[] 9 elements
+ - ca[] 9 elements
+ - ad[] 3 elements
+ - bd[] 3 elements
+
+ @cite dobted from David Eberly's papers, variables used in this function
correspond to variables used in pages 6 and 7 in the pdf
http://www.magic-software.com/Intersection.html
http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
@note Links are out-dated. (Kept to preserve origin and authorship)
- @param box1 Box 1
- @param box2 Box 2
- @param a Box 1's bounding sphere vector
- @param b Box 2's bounding sphere vector
- @param D Vector between Box 1 and Box 2's center points
- @param c Pointer to array of dot products of the axes of Box 1
- and Box 2.
- @param ca Pointer to array of unsigned dot products of the axes
- of Box 1 and Box 2.
- @param ad Pointer to array of dot products of Box 1 axes and D.
- @param bd Pointer to array of dot products of Box 2 axes and D.
- */
+ @param box1 Box 1
+ @param box2 Box 2
+ @param a Box 1's bounding sphere vector
+ @param b Box 2's bounding sphere vector
+ @param D Vector between Box 1 and Box 2's center points
+ @param c Pointer to array of dot products of the axes of Box 1
+ and Box 2.
+ @param ca Pointer to array of unsigned dot products of the axes
+ of Box 1 and Box 2.
+ @param ad Pointer to array of dot products of Box 1 axes and D.
+ @param bd Pointer to array of dot products of Box 2 axes and D.
+ */
static void fillSolidBoxSolidBoxInfo(
const Box & box1,
const Box & box2,
@@ -233,70 +233,70 @@ public:
double* ad,
double* bd);
- /**
- Performs a simple bounding sphere check between two boxes to determine
- whether these boxes could <i>possibly</i> intersect. This is a very
- cheap operation (three dot products, two sqrts and a few others). If
- it returns true, an intersection is possible, but not necessarily
- guaranteed.
-
- @param a Vector from box A's center to an outer vertex
- @param b Vector from box B's center to an outer vertex
- @param D Distance between the centers of the two boxes
-
- @return true - if possible intersection
- @return false - otherwise (This does not guarantee an intersection)
- */
+ /**
+ Performs a simple bounding sphere check between two boxes to determine
+ whether these boxes could <i>possibly</i> intersect. This is a very
+ cheap operation (three dot products, two sqrts and a few others). If
+ it returns true, an intersection is possible, but not necessarily
+ guaranteed.
+
+ @param a Vector from box A's center to an outer vertex
+ @param b Vector from box B's center to an outer vertex
+ @param D Distance between the centers of the two boxes
+
+ @return true - if possible intersection
+ @return false - otherwise (This does not guarantee an intersection)
+ */
static bool conservativeBoxBoxTest(
const Vector3 & a,
const Vector3 & b,
const Vector3 & D);
- /**
- Determines whether two fixed solid boxes intersect.
+ /**
+ Determines whether two fixed solid boxes intersect.
@note To speed up collision detection, the lastSeparatingAxis from
the previous time step can be passed in and that plane can be
checked first. If the separating axis was not saved, or if the
two boxes intersected then lastSeparatingAxis should equal -1.
- @cite Adobted from David Eberly's papers, variables used in this function
+ @cite Adobted from David Eberly's papers, variables used in this function
correspond to variables used in pages 6 and 7 in the pdf
http://www.magic-software.com/Intersection.html
http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
- @param box1 Box 1.
- @param box2 Box 2.
- @param lastSeparatingAxis Last separating axis.
- (optimization - see note)
+ @param box1 Box 1.
+ @param box2 Box 2.
+ @param lastSeparatingAxis Last separating axis.
+ (optimization - see note)
- @return true - Intersection.
- @return false - otherwise.
- */
+ @return true - Intersection.
+ @return false - otherwise.
+ */
static bool fixedSolidBoxIntersectsFixedSolidBox(
const Box& box1,
const Box& box2,
const int lastSeparatingAxis = -1);
/**
- Calculates the closest points on two lines with each other. If the
- lines are parallel then using the starting point, else calculate the
- closest point on each line to the other.
-
- @note This is very similiar to calculating the intersection of two lines.
- Logically then, the two points calculated would be identical if calculated
- with inifinite precision, but with the finite precision of floating point
- calculations, these values could (will) differ as the line slope approaches
- zero or inifinity.
-
- @cite variables and algorithm based on derivation at the following website:
- http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
-
- @param line1 Line 1.
- @param line2 Line 2.
- @param closest1 Closest point on line 1.
- @param closest2 Closest point on line 2.
- */
+ Calculates the closest points on two lines with each other. If the
+ lines are parallel then using the starting point, else calculate the
+ closest point on each line to the other.
+
+ @note This is very similiar to calculating the intersection of two lines.
+ Logically then, the two points calculated would be identical if calculated
+ with inifinite precision, but with the finite precision of floating point
+ calculations, these values could (will) differ as the line slope approaches
+ zero or inifinity.
+
+ @cite variables and algorithm based on derivation at the following website:
+ http://softsurfer.com/Archive/algorithm_0106/algorithm_0106.htm
+
+ @param line1 Line 1.
+ @param line2 Line 2.
+ @param closest1 Closest point on line 1.
+ @param closest2 Closest point on line 2.
+ */
static void closestPointsBetweenLineAndLine(
const Line & line1,
const Line & line2,
@@ -304,7 +304,7 @@ public:
Vector3 & closest2);
/**
- Calculates the depth of penetration between two fixed boxes.
+ Calculates the depth of penetration between two fixed boxes.
Contact normal faces away from box1 and into box2. If there is
contact, only one contact point is returned. The minimally
violated separating plane is computed
@@ -315,26 +315,26 @@ public:
the contact point is the midpoint of the smallest line
segment between the two edge lines
- @note This is very similiar to calculating the intersection of two lines.
- Logically then, the two points calculated would be identical if calculated
- with inifinite precision, but with the finite precision of floating point
- calculations, these values could (will) differ as the line slope approaches
- zero or inifinity.
+ @note This is very similiar to calculating the intersection of two lines.
+ Logically then, the two points calculated would be identical if calculated
+ with inifinite precision, but with the finite precision of floating point
+ calculations, these values could (will) differ as the line slope approaches
+ zero or inifinity.
- @cite adobted from David Eberly's papers, variables used in this function
+ @cite adobted from David Eberly's papers, variables used in this function
correspond to variables used in pages 6 and 7 in the pdf
http://www.magic-software.com/Intersection.html
http://www.magic-software.com/Documentation/DynamicCollisionDetection.pdf
- @param box1 Box 1
- @param box2 Box 2
- @param contactPoints Contact point between boxes. [Post Condition]
- @param contactNormals Surface normal at contact point. [Post Condition]
- @param lastSeparatingAxis Last separating axis. (Used for optimization)
+ @param box1 Box 1
+ @param box2 Box 2
+ @param contactPoints Contact point between boxes. [Post Condition]
+ @param contactNormals Surface normal at contact point. [Post Condition]
+ @param lastSeparatingAxis Last separating axis. (Used for optimization)
- @return Depth of penetration between the two boxes. If there is no
- intersection between the boxes, then a negative value is returned.
- */
+ @return Depth of penetration between the two boxes. If there is no
+ intersection between the boxes, then a negative value is returned.
+ */
static float penetrationDepthForFixedBoxFixedBox(
const Box& box1,
const Box& box2,
@@ -343,21 +343,21 @@ public:
const int lastSeparatingAxis = -1);
/**
- Calculates the depth of penetration between two fixed spheres as well
- as the deepest point of Sphere A that penetrates Sphere B. The normal
+ Calculates the depth of penetration between two fixed spheres as well
+ as the deepest point of Sphere A that penetrates Sphere B. The normal
returned points <B>away</B> from the object A, although it may
represent a perpendicular to either the faces of object B or object A
depending on their relative orientations.
- @param sphereA Fixed Sphere A.
- @param sphereB Fixed Sphere B.
- @param contactPoints Sphere A's deepest point that penetrates Sphere B.
- [Post Condition]
- @param contactNormals Normal at penetration point. [Post Condition]
+ @param sphereA Fixed Sphere A.
+ @param sphereB Fixed Sphere B.
+ @param contactPoints Sphere A's deepest point that penetrates Sphere B.
+ [Post Condition]
+ @param contactNormals Normal at penetration point. [Post Condition]
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
+ @return Depth of penetration. If there is no intersection between the
+ objects then the depth will be a negative value.
+ */
static float penetrationDepthForFixedSphereFixedSphere(
const class Sphere& sphereA,
const Sphere& sphereB,
@@ -365,125 +365,125 @@ public:
Array<Vector3>& contactNormals = ignoreArray);
/**
- Calculates the depth of penetration between a fixed sphere and a fixed
- box as well as the deepest point of the sphere that penetrates the box
- and the normal at that intersection.
-
- @note There are three possible intersections between a sphere and box.
- - Sphere completely contained in the box
- - Sphere intersects one edge
- - Sphere intersects one vertex
-
- The contact point and contact normal vary for each of these situations.
- - Sphere contained in Box:
- - Normal is based on side of least penetration (as is the depth calculation).
- - Point is based on center of sphere
- - Sphere intersects one edge
- - Normal is based on vector from the box center to the point of depth.
- - Point is closest point to the sphere on the line
- - Sphere intersects one vertex
- - Normal is based on vector from the box center to the vertex of penetration.
- - Point is vertex of penetration.
+ Calculates the depth of penetration between a fixed sphere and a fixed
+ box as well as the deepest point of the sphere that penetrates the box
+ and the normal at that intersection.
+
+ @note There are three possible intersections between a sphere and box.
+ - Sphere completely contained in the box
+ - Sphere intersects one edge
+ - Sphere intersects one vertex
+
+ The contact point and contact normal vary for each of these situations.
+ - Sphere contained in Box:
+ - Normal is based on side of least penetration (as is the depth calculation).
+ - Point is based on center of sphere
+ - Sphere intersects one edge
+ - Normal is based on vector from the box center to the point of depth.
+ - Point is closest point to the sphere on the line
+ - Sphere intersects one vertex
+ - Normal is based on vector from the box center to the vertex of penetration.
+ - Point is vertex of penetration.
@cite Adapted from Jim Arvo's method in Graphics Gems
See also http://www.win.tue.nl/~gino/solid/gdc2001depth.pdf
- @param sphere Fixed Sphere.
- @param box Fixed Box.
- @param contactPoints Sphere point that penetrates the box. [Post Condition]
- @param contactNormals Normal at the penetration point. [Post Condition]
+ @param sphere Fixed Sphere.
+ @param box Fixed Box.
+ @param contactPoints Sphere point that penetrates the box. [Post Condition]
+ @param contactNormals Normal at the penetration point. [Post Condition]
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
+ @return Depth of penetration. If there is no intersection between the
+ objects then the depth will be a negative value.
+ */
static float penetrationDepthForFixedSphereFixedBox(
const Sphere& sphere,
const Box& box,
Array<Vector3>& contactPoints,
Array<Vector3>& contactNormals = ignoreArray);
- /**
- Calculates the depth of penetration between a Fixed Sphere and a Fixed
- Plane as well as the deepest point of the sphere that penetrates the plane
- and the plane normal at that intersection.
-
- @param sphereA Fixed Sphere.
- @param planeB Fixed Plane.
- @param contactPoints Sphere point that penetrates the plane.
- [Post Condition]
- @param contactNormals Normal at penetration point. [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
+ /**
+ Calculates the depth of penetration between a Fixed Sphere and a Fixed
+ Plane as well as the deepest point of the sphere that penetrates the plane
+ and the plane normal at that intersection.
+
+ @param sphereA Fixed Sphere.
+ @param planeB Fixed Plane.
+ @param contactPoints Sphere point that penetrates the plane.
+ [Post Condition]
+ @param contactNormals Normal at penetration point. [Post Condition]
+
+ @return Depth of penetration. If there is no intersection between the
+ objects then the depth will be a negative value.
+ */
static float penetrationDepthForFixedSphereFixedPlane(
const Sphere& sphereA,
const class Plane& planeB,
Array<Vector3>& contactPoints,
Array<Vector3>& contactNormals = ignoreArray);
- /**
- Calculates the depth of penetration between a fixed box and a fixed
- plane as well as the vertexes of the box that penetrate the plane
- and the plane normals at those intersections.
-
- @param box Fixed Box.
- @param plane Fixed Plane.
- @param contactPoints Box points that penetrate the plane.
- [Post Condition]
- @param contactNormals Normals at penetration points [Post Condition]
-
- @return Depth of penetration. If there is no intersection between the
- objects then the depth will be a negative value.
- */
+ /**
+ Calculates the depth of penetration between a fixed box and a fixed
+ plane as well as the vertexes of the box that penetrate the plane
+ and the plane normals at those intersections.
+
+ @param box Fixed Box.
+ @param plane Fixed Plane.
+ @param contactPoints Box points that penetrate the plane.
+ [Post Condition]
+ @param contactNormals Normals at penetration points [Post Condition]
+
+ @return Depth of penetration. If there is no intersection between the
+ objects then the depth will be a negative value.
+ */
static float penetrationDepthForFixedBoxFixedPlane(
const Box& box,
const Plane& plane,
Array<Vector3>& contactPoints,
Array<Vector3>& contactNormals = ignoreArray);
- /**
- Calculates time between the intersection of a moving point and a fixed
- plane.
-
- @note This is only a one sided collision test. The side defined by
- the plane's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param point Moving point.
- @param velocity Point's velocity.
- @param plane Fixed plane.
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param outNormal Plane's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ plane.
+
+ @note This is only a one sided collision test. The side defined by
+ the plane's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
+
+ @param point Moving point.
+ @param velocity Point's velocity.
+ @param plane Fixed plane.
+ @param outLocation Location of collision. [Post Condition]
+ (Infinite vector on no collision)
+ @param outNormal Plane's surface normal. [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingPointFixedPlane(
- const Vector3& point,
- const Vector3& velocity,
- const class Plane& plane,
- Vector3& outLocation,
+ const Vector3& point,
+ const Vector3& velocity,
+ const class Plane& plane,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ triangle.
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
+ @note This is only a one sided collision test. The side defined by
+ the triangle's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
+ @param orig Moving point.
+ @param dir Point's velocity.
+ @param v0 Triangle vertex 1.
+ @param v1 Triangle vertex 2.
+ @param v2 Triangle vertex 3
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
inline static float collisionTimeForMovingPointFixedTriangle(
const Vector3& orig,
const Vector3& dir,
@@ -493,25 +493,25 @@ public:
return Ray::fromOriginAndDirection(orig, dir).intersectionTime(v0, v1, v2);
}
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ triangle.
+
+ @note This is only a one sided collision test. The side defined by
+ the triangle's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
+
+ @param orig Moving point.
+ @param dir Point's velocity.
+ @param v0 Triangle vertex 1.
+ @param v1 Triangle vertex 2.
+ @param v2 Triangle vertex 3
+ @param location Location of collision. [Post Condition]
+ (Infinite vector on no collision)
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
inline static float collisionTimeForMovingPointFixedTriangle(
const Vector3& orig,
const Vector3& dir,
@@ -526,24 +526,24 @@ public:
return t;
}
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param tri Fixed triangle.
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param normal Triangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ triangle.
+
+ @note This is only a one sided collision test. The side defined by
+ the triangle's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
+
+ @param orig Moving point.
+ @param dir Point's velocity.
+ @param tri Fixed triangle.
+ @param location Location of collision. [Post Condition]
+ (Infinite vector on no collision)
+ @param normal Triangle's surface normal. [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
inline static float collisionTimeForMovingPointFixedTriangle(
const Vector3& orig,
const Vector3& dir,
@@ -561,26 +561,26 @@ public:
return t;
}
- /**
- Calculates time between the intersection of a moving point and a fixed
- triangle.
-
- @note This is only a one sided collision test. The side defined by
- the triangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param orig Moving point.
- @param dir Point's velocity.
- @param v0 Triangle vertex 1.
- @param v1 Triangle vertex 2.
- @param v2 Triangle vertex 3
- @param location Location of collision. [Post Condition]
- (Infinite vector on no collision)
- @param normal Triangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ triangle.
+
+ @note This is only a one sided collision test. The side defined by
+ the triangle's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
+
+ @param orig Moving point.
+ @param dir Point's velocity.
+ @param v0 Triangle vertex 1.
+ @param v1 Triangle vertex 2.
+ @param v2 Triangle vertex 3
+ @param location Location of collision. [Post Condition]
+ (Infinite vector on no collision)
+ @param normal Triangle's surface normal. [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
inline static float collisionTimeForMovingPointFixedTriangle(
const Vector3& orig,
const Vector3& dir,
@@ -603,39 +603,39 @@ public:
<B>Beta API</B>
@cite Andrew Woo, from "Graphics Gems", Academic Press, 1990
- @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500)
+ @cite Optimized code by Pierre Terdiman, 2000 (~20-30% faster on Celeron 500)
@cite Epsilon value added by Klaus Hartmann
@cite http://www.codercorner.com/RayAABB.cpp
*/
static float collisionTimeForMovingPointFixedAABox(
- const Vector3& point,
- const Vector3& velocity,
+ const Vector3& point,
+ const Vector3& velocity,
const class AABox& box,
- Vector3& outLocation,
+ Vector3& outLocation,
bool& inside = ignoreBool,
Vector3& outNormal = ignore);
/**
- Calculates time between the intersection of a moving point and a fixed
- Axis-Aligned Box (AABox).
+ Calculates time between the intersection of a moving point and a fixed
+ Axis-Aligned Box (AABox).
- @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox.
+ @note Avoids the sqrt from collisionTimeForMovingPointFixedAABox.
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param box Fixed AAbox.
- @param location Location of collision. [Post Condition]
- @param Inside Does the ray originate inside the box? [Post Condition]
- @param normal Box's surface normal to collision [Post Condition]
+ @param point Moving point.
+ @param velocity Sphere's velocity.
+ @param box Fixed AAbox.
+ @param outLocation Location of collision. [Post Condition]
+ @param inside Does the ray originate inside the box? [Post Condition]
+ @param normal Box's surface normal to collision [Post Condition]
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static bool collisionLocationForMovingPointFixedAABox(
- const Vector3& point,
- const Vector3& velocity,
+ const Vector3& point,
+ const Vector3& velocity,
const class AABox& box,
- Vector3& outLocation,
+ Vector3& outLocation,
bool& inside = ignoreBool,
Vector3& normal = ignore);
@@ -648,8 +648,8 @@ public:
early-out branches and operations optimized for Intel Core2 architecture.
@param invDir 1/dir
- @param location Location of collision. [Post Condition]
- @param inside Does the ray originate inside the box? [Post Condition]
+ @param location Location of collision. [Post Condition]
+ @param inside Does the ray originate inside the box? [Post Condition]
@return True if the ray hits the box
*/
@@ -663,194 +663,194 @@ public:
bool& inside);
/**
- Calculates time between the intersection of a moving point and a fixed
- sphere.
+ Calculates time between the intersection of a moving point and a fixed
+ sphere.
- @note When ray is starts inside the rectangle, the exiting intersection
- is detected.
+ @note When ray is starts inside the rectangle, the exiting intersection
+ is detected.
- @param point Moving point.
- @param velocity Point's velocity.
- @param sphere Fixed Sphere.
- @param outLocation Location of collision. [Post Condition]
- @param outNormal Sphere's surface normal to collision [Post Condition]
+ @param point Moving point.
+ @param velocity Point's velocity.
+ @param sphere Fixed Sphere.
+ @param outLocation Location of collision. [Post Condition]
+ @param outNormal Sphere's surface normal to collision [Post Condition]
\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).
- @return Time until collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time until collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingPointFixedSphere(
- const Vector3& point,
- const Vector3& velocity,
- const class Sphere& sphere,
- Vector3& outLocation,
+ const Vector3& point,
+ const Vector3& velocity,
+ const class Sphere& sphere,
+ Vector3& outLocation,
Vector3& outNormal = ignore,
bool solid = false);
/**
- Calculates time between the intersection of a moving point and a fixed
- box.
+ Calculates time between the intersection of a moving point and a fixed
+ box.
- @note If the point is already inside the box, no collision: inf is returned.
+ @note If the point is already inside the box, no collision: inf is returned.
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param box Fixed box.
- @param location Position of collision. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
+ @param point Moving point.
+ @param velocity Sphere's velocity.
+ @param box Fixed box.
+ @param outLocation Position of collision. [Post Condition]
+ @param outNormal Box's surface normal to collision [Post Condition]
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingPointFixedBox(
- const Vector3& point,
- const Vector3& velocity,
- const class Box& box,
- Vector3& outLocation,
+ const Vector3& point,
+ const Vector3& velocity,
+ const class Box& box,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving point and a fixed
- rectangle defined by the points v0, v1, v2, & v3.
-
- @note This is only a one sided collision test. The side defined by
- the rectangle's surface normal is the only one tested. For a two sided
- collision, call the function once for each side's surface normal.
-
- @param point Moving point.
- @param velocity Sphere's velocity.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param location Location of collision [Post Condition]
- @param outNormal Rectangle's surface normal. [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ rectangle defined by the points v0, v1, v2, & v3.
+
+ @note This is only a one sided collision test. The side defined by
+ the rectangle's surface normal is the only one tested. For a two sided
+ collision, call the function once for each side's surface normal.
+
+ @param point Moving point.
+ @param velocity Sphere's velocity.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3
+ @param v3 Rectangle vertex 4.
+ @param outLocation Location of collision [Post Condition]
+ @param outNormal Rectangle's surface normal. [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingPointFixedRectangle(
- const Vector3& point,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& outLocation,
+ const Vector3& point,
+ const Vector3& velocity,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving point and a fixed
- capsule.
-
- @param point Moving point.
- @param velocity Point's velocity.
- @param capsule Fixed capsule.
- @param outLocation Location of collision. [Post Condition]
- @param outNormal Capsule's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingPointFixedCapsule(
- const Vector3& point,
- const Vector3& velocity,
- const class Capsule& capsule,
- Vector3& outLocation,
- Vector3& outNormal = ignore);
+ /**
+ Calculates time between the intersection of a moving point and a fixed
+ capsule.
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- triangle.
+ @param point Moving point.
+ @param velocity Point's velocity.
+ @param capsule Fixed capsule.
+ @param outLocation Location of collision. [Post Condition]
+ @param outNormal Capsule's surface normal to collision [Post Condition]
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param plane Fixed Plane.
- @param outLocation Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
+ static float collisionTimeForMovingPointFixedCapsule(
+ const Vector3& point,
+ const Vector3& velocity,
+ const class Capsule& capsule,
+ Vector3& outLocation,
+ Vector3& outNormal = ignore);
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving sphere and a fixed
+ triangle.
+
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param plane Fixed Plane.
+ @param outLocation Location of collision -- not center position of sphere
+ at the collision time. [Post Condition]
+ @param outNormal Box's surface normal to collision [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingSphereFixedPlane(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Plane& plane,
- Vector3& outLocation,
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const class Plane& plane,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- triangle.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param triangle Fixed Triangle. (collisions can happen on the back side of the triangle)
- @param outLocation Location of collision, if collision occurs -- not center position of sphere
- at the collision time. If there is interpenetration at the start, this point may be inside
+ /**
+ Calculates time between the intersection of a moving sphere and a fixed
+ triangle.
+
+ @param sphere The moving sphere.
+ @param velocity The sphere's velocity.
+ @param triangle Single-sided fixed triangle.
+ @param outLocation Location of collision, if collision occurs -- not center position of sphere
+ at the collision time. If there is interpenetration at the start, this point may be inside
the sphere.
@param b Barycentric coordinates. These are not valid unless collision occurs.
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time until collision. If there is no collision then the return
+ value will be finf().
+ */
static float collisionTimeForMovingSphereFixedTriangle(
- const class Sphere& sphere,
- const Vector3& velocity,
+ const class Sphere& sphere,
+ const Vector3& velocity,
const Triangle& triangle,
- Vector3& outLocation,
+ Vector3& outLocation,
float b[3] = (float*)&ignore);
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- rectangle defined by the points v0, v1, v2, & v3.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param outLocation Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ /**
+ Calculates time between the intersection of a moving sphere and a fixed
+ rectangle defined by the points v0, v1, v2, & v3.
+
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3
+ @param v3 Rectangle vertex 4.
+ @param outLocation Location of collision -- not center position of sphere
+ at the collision time. [Post Condition]
+ @param outNormal Box's surface normal to collision [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingSphereFixedRectangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- Vector3& outLocation,
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
- /**
- Calculates time between the intersection of a moving sphere and a fixed
- box.
+ /**
+ Calculates time between the intersection of a moving sphere and a fixed
+ box.
- @note This function will not detect an intersection between a moving object
- that is already interpenetrating the fixed object.
+ @note This function will not detect an intersection between a moving object
+ that is already interpenetrating the fixed object.
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param box Fixed box.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Box's surface normal to collision [Post Condition]
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param box Fixed box.
+ @param outLocation Location of collision -- not center position of sphere
+ at the collision time. [Post Condition]
+ @param outNormal Box's surface normal to collision [Post Condition]
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
static float collisionTimeForMovingSphereFixedBox(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Box& box,
- Vector3& outLocation,
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const class Box& box,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
/** Calculates time between the intersection of a moving sphere
@@ -860,199 +860,199 @@ public:
location is the closest point on the surface of the fixed sphere
to the center of the moving sphere.
- @param sphere Moving sphere.
+ @param sphere Moving sphere.
@param velocity Sphere's velocity.
- @param fixedSphere Fixed Sphere.
- @param outLocation Location of collision -- not center position of sphere
+ @param fixedSphere Fixed Sphere.
+ @param outLocation Location of collision -- not center position of sphere
at the collision time. [Post Condition]
- @param outNormal Moving sphere's surface normal to collision [Post Condition]
+ @param outNormal Moving sphere's surface normal to collision [Post Condition]
@return Time until collision. If there is no collision then the return
value will be inf().
*/
static float collisionTimeForMovingSphereFixedSphere(
- const Sphere& sphere,
- const Vector3& velocity,
- const Sphere& fixedSphere,
- Vector3& outLocation,
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Sphere& fixedSphere,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
/**
- Calculates time between the intersection of a moving sphere and a fixed
- capsule.
-
- @note This won't detect a collision if the sphere is already
- interpenetrating the capsule.
-
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param capsule Fixed capsule.
- @param location Location of collision -- not center position of sphere
- at the collision time. [Post Condition]
- @param outNormal Capsule's surface normal to the collision [Post Condition]
-
- @return Time til collision. If there is no collision then the return
- value will be inf().
- */
- static float collisionTimeForMovingSphereFixedCapsule(
- const class Sphere& sphere,
- const Vector3& velocity,
- const class Capsule& capsule,
- Vector3& outLocation,
+ Calculates time between the intersection of a moving sphere and a fixed
+ capsule.
+
+ @note This won't detect a collision if the sphere is already
+ interpenetrating the capsule.
+
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param capsule Fixed capsule.
+ @param outLocation Location of collision -- not center position of sphere
+ at the collision time. [Post Condition]
+ @param outNormal Capsule's surface normal to the collision [Post Condition]
+
+ @return Time til collision. If there is no collision then the return
+ value will be inf().
+ */
+ static float collisionTimeForMovingSphereFixedCapsule(
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const class Capsule& capsule,
+ Vector3& outLocation,
Vector3& outNormal = ignore);
/**
- Finds the direction of bounce that a sphere would have when it
- intersects an object with the given time of collision, the
- collision location and the collision normal.
+ Finds the direction of bounce that a sphere would have when it
+ intersects an object with the given time of collision, the
+ collision location and the collision normal.
- @note This function works like a pong style ball bounce.
+ @note This function works like a pong style ball bounce.
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param collisionTime Time of collision.
- @param collisionLocation Collision location.
- @param collisionNormal Surface collision normal.
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param collisionTime Time of collision.
+ @param collisionLocation Collision location.
+ @param collisionNormal Surface collision normal.
- @return Direction of bounce.
- */
+ @return Direction of bounce.
+ */
static Vector3 bounceDirection(
- const class Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation,
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const float collisionTime,
+ const Vector3& collisionLocation,
const Vector3& collisionNormal);
/**
- Finds the direction of slide given a moving sphere, its velocity, the
- time of collision and the collision location. This function works as
- if the sphere intersects the surface and continues to hug it.
+ Finds the direction of slide given a moving sphere, its velocity, the
+ time of collision and the collision location. This function works as
+ if the sphere intersects the surface and continues to hug it.
- @note The result will work well for calculating the movement of a player
- who collides with an object and continues moving along the object instead
- of just bouncing off it.
+ @note The result will work well for calculating the movement of a player
+ who collides with an object and continues moving along the object instead
+ of just bouncing off it.
- @param sphere Moving sphere.
- @param velocity Sphere's velocity.
- @param collisionTime Time of collision
- @param collisionLocation Collision location.
+ @param sphere Moving sphere.
+ @param velocity Sphere's velocity.
+ @param collisionTime Time of collision
+ @param collisionLocation Collision location.
- @return Direction of slide.
- */
+ @return Direction of slide.
+ */
static Vector3 slideDirection(
- const class Sphere& sphere,
- const Vector3& velocity,
- const float collisionTime,
- const Vector3& collisionLocation);
+ const class Sphere& sphere,
+ const Vector3& velocity,
+ const float collisionTime,
+ const Vector3& collisionLocation);
- /**
- Finds the closest point on a line segment to a given point.
+ /**
+ Finds the closest point on a line segment to a given point.
- @param v0 line vertex 1.
- @param v1 line vertex 2.
- @param point External point.
+ @param v0 line vertex 1.
+ @param v1 line vertex 2.
+ @param point External point.
- @return Closests point to <code>point</code> on the line segment.
- */
- static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& point);
+ @return Closests point to <code>point</code> on the line segment.
+ */
+ static Vector3 closestPointOnLineSegment(
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& point);
/**
- Finds the closest point on a line segment to a given point.
+ Finds the closest point on a line segment to a given point.
- @note This is an optimization to closestPointOnLineSegment. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
+ @note This is an optimization to closestPointOnLineSegment. Edge length
+ and direction can be used in this function if already pre-calculated. This
+ prevents doing the same work twice.
- @param v0 line vertex 0.
- @param v1 line vertex 1.
+ @param v0 line vertex 0.
+ @param v1 line vertex 1.
@param edgeDirection The direction of the segment (unit length).
@param edgeLength The length of the segment.
@param point External point.
- @return Closests point to <code>point</code> on the line segment.
- */
+ @return Closests point to <code>point</code> on the line segment.
+ */
static Vector3 closestPointOnLineSegment(
- const Vector3& v0,
- const Vector3& v1,
+ const Vector3& v0,
+ const Vector3& v1,
const Vector3& edgeDirection,
float edgeLength,
- const Vector3& point);
+ const Vector3& point);
/**
- Finds the closest point on the perimeter of the triangle to an external point;
- given a triangle defined by three points v0, v1, & v2, and the external point.
+ Finds the closest point on the perimeter of the triangle to an external point;
+ given a triangle defined by three points v0, v1, & v2, and the external point.
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param point External point.
+ @param v0 Triangle vertex 0.
+ @param v1 Triangle vertex 1.
+ @param v2 Triangle vertex 2.
+ @param point External point.
- @return Closests point to <code>point</code> on the perimeter of the
- triangle.
- */
+ @return Closests point to <code>point</code> on the perimeter of the
+ triangle.
+ */
static Vector3 closestPointOnTrianglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& point);
-
- /**
- Finds the closest point on the perimeter of the triangle to an external point;
- given a triangle defined by the array of points v, its edge directions and
- their lengths, as well as the external point.
-
- @note This is an optimization to closestPointToTrianglePerimeter. Edge length
- and direction can be used in this function if already pre-calculated. This
- prevents doing the same work twice.
-
- @param v Triangle vertices.
- @param point External point.
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& point);
+
+ /**
+ Finds the closest point on the perimeter of the triangle to an external point;
+ given a triangle defined by the array of points v, its edge directions and
+ their lengths, as well as the external point.
+
+ @note This is an optimization to closestPointToTrianglePerimeter. Edge length
+ and direction can be used in this function if already pre-calculated. This
+ prevents doing the same work twice.
+
+ @param v Triangle vertices.
+ @param point External point.
@param edgeIndex The point lies on the edge between v[edgeIndex] and v[(edgeIndex + 1) % 3]
- @return Closest point to <code>point</code> on the perimeter of the
- triangle.
- */
+ @return Closest point to <code>point</code> on the perimeter of the
+ triangle.
+ */
static Vector3 closestPointOnTrianglePerimeter(
const Vector3 v[3],
const Vector3 edgeDirection[3],
const float edgeLength[3],
- const Vector3& point,
+ const Vector3& point,
int& edgeIndex);
/**
- Tests whether a point is contained within the triangle defined by
- v0, v1, and v2 and its plane's normal.
-
- @param v0 Triangle vertex 0.
- @param v1 Triangle vertex 1.
- @param v2 Triangle vertex 2.
- @param normal Normal to triangle's plane.
- @param point The point in question.
- @param primaryAxis Primary axis of triangle. This will be detected
- if not given. This parameter is provided as an optimization.
+ Tests whether a point is contained within the triangle defined by
+ v0, v1, and v2 and its plane's normal.
+
+ @param v0 Triangle vertex 0.
+ @param v1 Triangle vertex 1.
+ @param v2 Triangle vertex 2.
+ @param normal Normal to triangle's plane.
+ @param point The point in question.
+ @param primaryAxis Primary axis of triangle. This will be detected
+ if not given. This parameter is provided as an optimization.
@param b Barycentric coordinates; b[i] is the weight on v[i]
- @return true - if point is inside the triangle.
- @return false - otherwise
- */
+ @return true - if point is inside the triangle.
+ @return false - otherwise
+ */
static bool isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& normal,
const Vector3& point,
float b[3],
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS);
inline static bool isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
- const Vector3& point,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& normal,
+ const Vector3& point,
Vector3::Axis primaryAxis = Vector3::DETECT_AXIS) {
float b[3];
@@ -1060,70 +1060,70 @@ public:
}
/**
- Tests for the intersection of a moving sphere and a fixed box in a
- given time limit.
+ Tests for the intersection of a moving sphere and a fixed box in a
+ given time limit.
- @note Returns true if any part of the sphere is inside the box
- during the time period (inf means "ever"). Useful for
- performing bounding-box collision detection.
+ @note Returns true if any part of the sphere is inside the box
+ during the time period (inf means "ever"). Useful for
+ performing bounding-box collision detection.
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param box Fixed box.
- @param timeLimit Time limit for intersection test.
+ @param sphere Moving sphere.
+ @param velocity Velocity of moving sphere.
+ @param box Fixed box.
+ @param timeLimit Time limit for intersection test.
- @return true - if the two objects will touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two objects will touch.
+ @return false - if there is no intersection.
+ */
static bool movingSpherePassesThroughFixedBox(
const Sphere& sphere,
const Vector3& velocity,
const Box& box,
double timeLimit = inf());
- /**
- Tests for the intersection of a moving sphere and a fixed sphere in a
- given time limit.
+ /**
+ Tests for the intersection of a moving sphere and a fixed sphere in a
+ given time limit.
- @note This function will not detect an intersection between a moving object
- that is already interpenetrating the fixed object.
+ @note This function will not detect an intersection between a moving object
+ that is already interpenetrating the fixed object.
- @param sphere Moving sphere.
- @param velocity Velocity of moving sphere.
- @param fixedSphere Fixed sphere.
- @param timeLimit Time limit for intersection test.
+ @param sphere Moving sphere.
+ @param velocity Velocity of moving sphere.
+ @param fixedSphere Fixed sphere.
+ @param timeLimit Time limit for intersection test.
- @return true - if the two spheres will touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two spheres will touch.
+ @return false - if there is no intersection.
+ */
static bool movingSpherePassesThroughFixedSphere(
const Sphere& sphere,
const Vector3& velocity,
const Sphere& fixedSphere,
double timeLimit = inf());
- /**
- Tests for the intersection of two fixed spheres.
+ /**
+ Tests for the intersection of two fixed spheres.
- @param sphere1 Fixed sphere 1.
- @param sphere2 Fixed sphere 2.
+ @param sphere1 Fixed sphere 1.
+ @param sphere2 Fixed sphere 2.
- @return true - if the two spheres touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two spheres touch.
+ @return false - if there is no intersection.
+ */
static bool fixedSolidSphereIntersectsFixedSolidSphere(
const Sphere& sphere1,
const Sphere& sphere2);
- /**
- Tests for the intersection of a fixed sphere and a fixed box.
+ /**
+ Tests for the intersection of a fixed sphere and a fixed box.
- @param sphere Fixed sphere.
- @param box Fixed box.
+ @param sphere Fixed sphere.
+ @param box Fixed box.
- @return true - if the two objects touch.
- @return false - if there is no intersection.
- */
+ @return true - if the two objects touch.
+ @return false - if there is no intersection.
+ */
static bool fixedSolidSphereIntersectsFixedSolidBox(
const Sphere& sphere,
const Box& box);
@@ -1137,67 +1137,67 @@ public:
const Triangle& triangle);
/**
- Tests whether a point is inside a rectangle defined by the vertexes
- v0, v1, v2, & v3, and the rectangle's plane normal.
-
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param normal Normal to rectangle's plane.
- @param point The point in question.
-
- @return true - if point is inside the rectangle.
- @return false - otherwise
- */
+ Tests whether a point is inside a rectangle defined by the vertexes
+ v0, v1, v2, & v3, and the rectangle's plane normal.
+
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3.
+ @param v3 Rectangle vertex 4.
+ @param normal Normal to rectangle's plane.
+ @param point The point in question.
+
+ @return true - if point is inside the rectangle.
+ @return false - otherwise
+ */
static bool isPointInsideRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& normal,
- const Vector3& point);
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& normal,
+ const Vector3& point);
/**
- Finds the closest point on the perimeter of the rectangle to an
- external point; given a rectangle defined by four points v0, v1,
- v2, & v3, and the external point.
-
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3.
- @param v3 Rectangle vertex 4.
- @param point External point.
-
- @return Closests point to <code>point</code> on the perimeter of the
- rectangle.
- */
+ Finds the closest point on the perimeter of the rectangle to an
+ external point; given a rectangle defined by four points v0, v1,
+ v2, & v3, and the external point.
+
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3.
+ @param v3 Rectangle vertex 4.
+ @param point External point.
+
+ @return Closests point to <code>point</code> on the perimeter of the
+ rectangle.
+ */
static Vector3 closestPointToRectanglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& point);
/**
- Finds the closest point in the rectangle to an external point; Given
- a rectangle defined by four points v0, v1, v2, & v3, and the external
- point.
+ Finds the closest point in the rectangle to an external point; Given
+ a rectangle defined by four points v0, v1, v2, & v3, and the external
+ point.
- @param v0 Rectangle vertex 1.
- @param v1 Rectangle vertex 2.
- @param v2 Rectangle vertex 3
- @param v3 Rectangle vertex 4.
- @param point External point.
+ @param v0 Rectangle vertex 1.
+ @param v1 Rectangle vertex 2.
+ @param v2 Rectangle vertex 3
+ @param v3 Rectangle vertex 4.
+ @param point External point.
@return Closet point in the rectangle to the external point.
- */
- static Vector3 closestPointToRectangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& v3,
- const Vector3& point);
+ */
+ static Vector3 closestPointToRectangle(
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& v3,
+ const Vector3& point);
};
} // namespace
diff --git a/dep/g3dlite/include/G3D/Color1.h b/dep/g3dlite/include/G3D/Color1.h
index 0f68c84b363..6066fdcb751 100644
--- a/dep/g3dlite/include/G3D/Color1.h
+++ b/dep/g3dlite/include/G3D/Color1.h
@@ -1,30 +1,29 @@
/**
- @file Color1.h
+ \file G3D/Color1.h
Monochrome Color class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2009-03-20
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2007-01-31
+ \edited 2011-08-20
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_COLOR1_H
-#define G3D_COLOR1_H
+#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. This is just a float, but it has nice semantics
- because a scaling by 255 automatically occurs when switching between
- fixed point (Color1uint8) and floating point (Color1) formats.
+ Monochrome color.
*/
class Color1 {
private:
@@ -46,6 +45,9 @@ public:
inline explicit Color1(float v) : value(v) {
}
+
+ inline explicit Color1(unorm8 v) : value(v) {
+ }
inline bool isZero() const {
return value == 0.0f;
@@ -62,7 +64,7 @@ public:
/** Returns the value three times */
class Color3 rgb() const;
- Color1 (const class Color1uint8& other);
+ explicit Color1(const class Color1unorm8& other);
void serialize(class BinaryOutput& bo) const;
void deserialize(class BinaryInput& bi);
@@ -71,6 +73,7 @@ public:
return Color1(value + other.value);
}
+ /** \deprecated */
Color1 operator+ (const float other) const {
return Color1(value + other);
}
@@ -89,6 +92,7 @@ public:
return Color1(value - other.value);
}
+ /** \deprecated */
Color1 operator- (const float other) const {
return Color1(value - other);
}
@@ -101,6 +105,26 @@ public:
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);
}
@@ -140,5 +164,8 @@ struct HashTrait<G3D::Color1> {
}
};
+inline G3D::Color1 operator*(float f, G3D::Color1 c) {
+ return c * f;
+}
#endif
diff --git a/dep/g3dlite/include/G3D/Color1uint8.h b/dep/g3dlite/include/G3D/Color1uint8.h
deleted file mode 100644
index 092099d0d17..00000000000
--- a/dep/g3dlite/include/G3D/Color1uint8.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/Color3.h b/dep/g3dlite/include/G3D/Color3.h
index bffe434fc27..6eedf252233 100644
--- a/dep/g3dlite/include/G3D/Color3.h
+++ b/dep/g3dlite/include/G3D/Color3.h
@@ -1,16 +1,16 @@
/**
- @file Color3.h
+ \file Color3.h
Color class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library
+ \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 2009-04-28
+ \created 2001-06-02
+ \edited 2013-03-29
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -40,26 +40,41 @@ private:
public:
/**
- Does not initialize fields.
+ \brief Initializes to all zero.
*/
- Color3();
+ 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).
*/
- Color3(const Any& any);
+ explicit Color3(const Any& any);
+ Color3& operator=(const Any& a);
+
/** Converts the Color3 to an Any. */
- operator Any() const;
+ Any toAny() const;
explicit Color3(class BinaryInput& bi);
Color3(float r, float g, float b);
- Color3(float v) : r(v), g(v), b(v) {}
+
+ /** \brief Initializes all channels to \a v */
+ explicit Color3(float v) : r(v), g(v), b(v) {}
explicit Color3(const class Vector3& v);
@@ -75,7 +90,7 @@ public:
*/
Color3 (const Color3& other);
- Color3 (const class Color3uint8& other);
+ Color3 (const class Color3unorm8& other);
inline bool isZero() const {
return (r == 0.0f) && (g == 0.0f) && (b == 0.0f);
@@ -92,6 +107,12 @@ public:
*/
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();
@@ -140,10 +161,15 @@ public:
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
@@ -258,11 +284,11 @@ inline G3D::Color3 operator* (const G3D::Color3& c, G3D::Color1& s) {
return c * s.value;
}
-
-//----------------------------------------------------------------------------
-inline Color3::Color3 () {
+inline G3D::Color3 operator/ (float s, const G3D::Color3& c) {
+ return c * (1.0f/s);
}
+
//----------------------------------------------------------------------------
inline Color3::Color3(float fX, float fY, float fZ) {
@@ -414,11 +440,36 @@ inline Color3 Color3::cross (const Color3& rkVector) const {
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);
- kCross.unitize();
- return kCross;
+ 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
diff --git a/dep/g3dlite/include/G3D/Color3uint8.h b/dep/g3dlite/include/G3D/Color3uint8.h
deleted file mode 100644
index 7a1cc79d94d..00000000000
--- a/dep/g3dlite/include/G3D/Color3uint8.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/Color4.h b/dep/g3dlite/include/G3D/Color4.h
index 0be0c25879f..424e3289dcd 100644
--- a/dep/g3dlite/include/G3D/Color4.h
+++ b/dep/g3dlite/include/G3D/Color4.h
@@ -48,16 +48,16 @@ public:
Color4(const Any& any);
/** Converts the Color4 to an Any. */
- operator Any() const;
+ Any toAny() const;
/**
- * Does not initialize fields.
+ Initializes to all zero
*/
- Color4 ();
+ Color4() : r(0), g(0), b(0), a(0) {}
Color4(const Color3& c3, float a = 1.0);
- Color4(const class Color4uint8& c);
+ Color4(const class Color4unorm8& c);
Color4(class BinaryInput& bi);
@@ -191,12 +191,6 @@ inline Color4 operator*(const Color3& c3, const Color4& c4) {
//----------------------------------------------------------------------------
-inline Color4::Color4 () {
- // For efficiency in construction of large arrays of vectors, the
- // default constructor does not initialize the vector.
-}
-
-//----------------------------------------------------------------------------
inline Color4::Color4(const Color3& c3, float a) {
r = c3.r;
diff --git a/dep/g3dlite/include/G3D/Color4uint8.h b/dep/g3dlite/include/G3D/Color4uint8.h
deleted file mode 100644
index 2cd3c662788..00000000000
--- a/dep/g3dlite/include/G3D/Color4uint8.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/Cone.h b/dep/g3dlite/include/G3D/Cone.h
index d801a9b348f..f521dc4dcbd 100644
--- a/dep/g3dlite/include/G3D/Cone.h
+++ b/dep/g3dlite/include/G3D/Cone.h
@@ -61,6 +61,19 @@ public:
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
diff --git a/dep/g3dlite/include/G3D/ConvexPolyhedron.h b/dep/g3dlite/include/G3D/ConvexPolyhedron.h
index a6fdd62cf90..ea38c02baf2 100644
--- a/dep/g3dlite/include/G3D/ConvexPolyhedron.h
+++ b/dep/g3dlite/include/G3D/ConvexPolyhedron.h
@@ -34,7 +34,7 @@ private:
friend class ConvexPolyhedron;
- Array<Vector3> _vertex;
+ Array<Vector3> _vertex;
public:
diff --git a/dep/g3dlite/include/G3D/CoordinateFrame.h b/dep/g3dlite/include/G3D/CoordinateFrame.h
index c83754abb77..a2cc1f1a20c 100644
--- a/dep/g3dlite/include/G3D/CoordinateFrame.h
+++ b/dep/g3dlite/include/G3D/CoordinateFrame.h
@@ -1,12 +1,12 @@
/**
- @file CoordinateFrame.h
+ \file G3D/CoordinateFrame.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-03-04
- @edited 2009-04-29
+ \created 2001-03-04
+ \edited 2012-07-29
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -33,9 +33,10 @@
namespace G3D {
class Any;
+class Frustum;
/**
- A rigid body RT (rotation-translation) transformation.
+\brief A rigid body RT (rotation-translation) transformation.
CoordinateFrame abstracts a 4x4 matrix that maps object space to world space:
@@ -53,28 +54,28 @@ Convert to Matrix4 using CoordinateFrame::toMatrix4. You <I>can</I> construct a
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
+\sa G3D::UprightFrame, G3D::PhysicsFrame, G3D::Matrix4, G3D::Quat
*/
class CoordinateFrame {
public:
/** Takes object space points to world space. */
- Matrix3 rotation;
+ Matrix3 rotation;
- /** Takes object space points to world space. */
- Vector3 translation;
+ /** 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), (vector3 expr))
+ - CFrame((matrix3 expr), (Point3 expr))
- CFrame::fromXYZYPRDegrees(#, #, #, #, #, #)
- - CFrame { rotation = (matrix3 expr), translation = (vector3 expr) }
- - Vector3( ... )
+ - CFrame { rotation = (Matrix3 expr), translation = (Point3 expr) }
+ - Point3( ... )
- Matrix3( ... )
*/
CoordinateFrame(const Any& any);
/** Converts the CFrame to an Any. */
- operator Any() const;
+ Any toAny() const;
inline bool operator==(const CoordinateFrame& other) const {
return (translation == other.translation) && (rotation == other.rotation);
@@ -95,16 +96,16 @@ public:
*/
CoordinateFrame();
- CoordinateFrame(const Vector3& _translation) :
+ CoordinateFrame(const Point3& _translation) :
rotation(Matrix3::identity()), translation(_translation) {
}
- CoordinateFrame(const Matrix3 &rotation, const Vector3 &translation) :
+ CoordinateFrame(const Matrix3& rotation, const Point3& translation) :
rotation(rotation), translation(translation) {
}
- CoordinateFrame(const Matrix3 &rotation) :
- rotation(rotation), translation(Vector3::zero()) {
+ CoordinateFrame(const Matrix3& rotation) :
+ rotation(rotation), translation(Point3::zero()) {
}
CoordinateFrame(const class UprightFrame& f);
@@ -187,26 +188,25 @@ public:
/**
Transforms the point into world space.
*/
- inline Vector3 pointToWorldSpace(const Vector3& v) const {
- return Vector3(
- rotation[0][0] * v[0] + rotation[0][1] * v[1] + rotation[0][2] * v[2] + translation[0],
- rotation[1][0] * v[0] + rotation[1][1] * v[1] + rotation[1][2] * v[2] + translation[1],
- rotation[2][0] * v[0] + rotation[2][1] * v[1] + rotation[2][2] * v[2] + translation[2]);
+ 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 Vector3 pointToObjectSpace(const Vector3& v) const {
+ 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(rotation.determinant(), 1.0f));
- return Vector3(
- rotation[0][0] * p[0] + rotation[1][0] * p[1] + rotation[2][0] * p[2],
- rotation[0][1] * p[0] + rotation[1][1] * p[1] + rotation[2][1] * p[2],
- rotation[0][2] * p[0] + rotation[1][2] * p[1] + rotation[2][2] * p[2]);
+ 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]);
}
/**
@@ -224,6 +224,8 @@ public:
Ray toWorldSpace(const Ray& r) const;
+ Frustum toWorldSpace(const Frustum& f) const;
+
/**
Transforms the vector into object space (no translation).
*/
@@ -237,18 +239,20 @@ public:
return v * rotation;
}
- void pointToWorldSpace(const Array<Vector3>& v, Array<Vector3>& vout) const;
+ 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<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;
@@ -260,7 +264,7 @@ public:
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;
@@ -287,17 +291,32 @@ public:
return CoordinateFrame(rotation, translation - v);
}
- void lookAt(const Vector3& target);
- void lookAt(
- const Vector3& target,
- Vector3 up);
+ /**
+ 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.
- /** The direction this camera is looking (its negative z axis)*/
- inline Vector3 lookVector() const {
- return -rotation.column(2);
- }
+ \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;
@@ -307,24 +326,26 @@ public:
}
inline Vector3 rightVector() const {
- return rotation.column(0);
- }
+ 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);
+ 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;
+ CoordinateFrame lerp
+ (const CoordinateFrame& other,
+ float alpha) const;
};
diff --git a/dep/g3dlite/include/G3D/Crypto.h b/dep/g3dlite/include/G3D/Crypto.h
index 56c816a4977..d5c6f42ed14 100644
--- a/dep/g3dlite/include/G3D/Crypto.h
+++ b/dep/g3dlite/include/G3D/Crypto.h
@@ -1,18 +1,19 @@
/**
- @file Crypto.h
+ \file G3D/Crypto.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2006-03-29
- @edited 2006-04-06
+ \created 2006-03-29
+ \edited 2011-06-21
*/
-#ifndef G3D_CRYPTO_H
-#define G3D_CRYPTO_H
+#ifndef G3D_Crypto_h
+#define G3D_Crypto_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
+#include "G3D/System.h"
#include <string>
namespace G3D {
@@ -33,6 +34,24 @@ public:
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];
}
@@ -56,6 +75,18 @@ public:
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;
+ }
};
@@ -79,7 +110,7 @@ public:
@cite Based on implementation by L. Peter Deutsch, ghost@aladdin.com
*/
- MD5Hash md5(const void* bytes, size_t numBytes);
+ static MD5Hash md5(const void* bytes, size_t numBytes);
/**
Returns the nth prime less than 2000 in constant time. The first prime has index
diff --git a/dep/g3dlite/include/G3D/Cylinder.h b/dep/g3dlite/include/G3D/Cylinder.h
index 85eba77b794..ef049e10879 100644
--- a/dep/g3dlite/include/G3D/Cylinder.h
+++ b/dep/g3dlite/include/G3D/Cylinder.h
@@ -26,22 +26,22 @@ class AABox;
*/
class Cylinder {
private:
- Vector3 p1;
- Vector3 p2;
+ Vector3 p1;
+ Vector3 p2;
- float mRadius;
+ 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;
+ 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
diff --git a/dep/g3dlite/include/G3D/FileNotFound.h b/dep/g3dlite/include/G3D/FileNotFound.h
new file mode 100644
index 00000000000..dc756f329fb
--- /dev/null
+++ b/dep/g3dlite/include/G3D/FileNotFound.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/FileSystem.h b/dep/g3dlite/include/G3D/FileSystem.h
index b2a6e86520c..ae3239d9dc5 100644
--- a/dep/g3dlite/include/G3D/FileSystem.h
+++ b/dep/g3dlite/include/G3D/FileSystem.h
@@ -1,10 +1,10 @@
/**
- @file FileSystem.h
+ \file FileSystem.h
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @author 2002-06-06
- @edited 2010-02-05
+ \author 2002-06-06
+ \edited 2012-03-26
*/
#ifndef G3D_FileSystem_h
#define G3D_FileSystem_h
@@ -12,6 +12,8 @@
#include "G3D/platform.h"
#include "G3D/Array.h"
#include "G3D/Table.h"
+#include "G3D/Set.h"
+#include "G3D/GMutex.h"
namespace G3D {
@@ -34,11 +36,12 @@ namespace G3D {
<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
- TODO: make threadsafe!
*/
class FileSystem {
public:
@@ -63,7 +66,7 @@ public:
ListSettings() :
files(true),
directories(true),
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
caseSensitive(true),
# else
caseSensitive(false),
@@ -111,8 +114,13 @@ private:
/** When this entry was last updated */
double lastChecked;
- /** Case-independent comparison on Windows */
- bool contains(const std::string& child) const;
+ 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);
@@ -132,116 +140,80 @@ private:
FileSystem();
static FileSystem& instance();
+ static GMutex mutex;
-# ifdef G3D_WIN32
- /** On Windows, the drive letters that form the file system roots.*/
+
+# ifdef G3D_WINDOWS
+ /** \copydoc drives */
const Array<std::string>& _drives();
# 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 */
+ /** \copydoc inZipfile */
bool _inZipfile(const std::string& path, std::string& zipfile);
- /** 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) */
+ /** \copydoc clearCache */
void _clearCache(const std::string& path);
+ /** \copydoc inZipfile */
bool _inZipfile(const std::string& path) {
std::string ignore;
return inZipfile(path, ignore);
}
- /** Set the cacheLifetime().
- \param t in seconds */
+ /** \copydoc setCacheLifetime */
void _setCacheLifetime(float t);
- /** A cache is used to optimize repeated calls. A cache entry is considered
- valid for this many seconds after it has been checked. */
+ /** \copydoc cacheLifetime */
float _cacheLifetime() const {
return m_cacheLifetime;
}
- /** Creates the directory named, including any subdirectories
- that do not already exist.
-
- The directory must not be inside a zipfile.
-
- Flushes the cache.
- */
+ /** \copydoc createDirectory */
void _createDirectory(const std::string& path);
- /** 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.
-
- \param trustCache If true, uses the cache for optimizing repeated calls
- in the same parent directory.
- */
- bool _exists(const std::string& f, bool trustCache = true);
+ /** \copydoc exists */
+ bool _exists(const std::string& f, bool trustCache = true, bool caseSensitive =
+#ifdef G3D_WINDOWS
+ false
+#else
+ true
+#endif
+ );
- /** Known bug: does not work inside zipfiles */
+ /** \copydoc isDirectory */
bool _isDirectory(const std::string& path);
- /** Known bug: does not work inside zipfiles */
+ /** \copydoc isFile */
bool _isFile(const std::string& path) {
return ! isDirectory(path);
}
- /**
- \param srcPath Must name a file.
- \param dstPath Must not contain a zipfile.
-
- Flushes the cache.
- */
+ /** \copydoc copyFile */
void _copyFile(const std::string& srcPath, const std::string& dstPath);
- /** 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)
- */
+ /** \copydoc resolve */
std::string _resolve(const std::string& path, const std::string& cwd = currentDirectory());
- /** Returns true if \param dst does not exist or \param src is newer than \param dst,
- according to their time stamps.
-
- Known bug: does not work inside zipfiles.
- */
+ /** \copydoc isNewer */
bool _isNewer(const std::string& src, const std::string& dst);
- /** The current working directory (cwd). Only ends in a slash if this is the root of the file system. */
+ /** \copydoc currentDirectory */
std::string _currentDirectory();
- /** Returns the length of the file in bytes, or -1 if the file could not be opened. */
+ /** \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);
- /** 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).
-
- */
+ /** \copydoc list */
void _list(const std::string& spec, Array<std::string>& result, const ListSettings& listSettings = ListSettings());
- /** 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" */
+ /** \copydoc isZipfile */
bool _isZipfile(const std::string& path);
- /** list() files */
+ /** \copydoc getFiles */
void _getFiles(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
ListSettings set;
set.includeParentPath = includeParentPath;
@@ -250,7 +222,7 @@ private:
return list(spec, result, set);
}
- /** list() directories */
+ /** \copydoc getDirectories */
void _getDirectories(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
ListSettings set;
set.includeParentPath = includeParentPath;
@@ -259,12 +231,13 @@ private:
return list(spec, result, set);
}
- /** Same as the C standard library fopen, but updates the file cache
- to acknowledge the new file on a write operation. */
+ /** \copydoc fopen */
FILE* _fopen(const char* filename, const char* mode);
-public:
+ /** \copydoc removeFile */
+ void _removeFile(const std::string& path);
+public:
/** Create the common instance. */
static void init();
@@ -272,111 +245,267 @@ public:
/** Destroy the common instance. */
static void cleanup();
-# ifdef G3D_WIN32
- /** \copydoc _drives */
+# ifdef G3D_WINDOWS
+ /** On Windows, the drive letters that form the file system roots.*/
static const Array<std::string>& drives() {
- return instance()._drives();
+ mutex.lock();
+ const Array<std::string>& s = instance()._drives();
+ mutex.unlock();
+ return s;
}
# endif
- /** \copydoc _inZipfile */
+ /** 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) {
- return instance()._inZipfile(path, zipfile);
+ mutex.lock();
+ bool b = instance()._inZipfile(path, zipfile);
+ mutex.unlock();
+ return b;
}
- /** \copydoc _clearCache */
+ /** 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();
}
- /** \copydoc _fopen */
+
+ /** 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) {
- return instance()._fopen(filename, 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) {
- return instance()._inZipfile(path);
+ mutex.lock();
+ bool b = instance()._inZipfile(path);
+ mutex.unlock();
+ return b;
}
- /** \copydoc isZipfile */
+
+ /**
+ \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) {
- return instance()._isZipfile(path);
+ mutex.lock();
+ bool b = instance()._isZipfile(path);
+ mutex.unlock();
+ return b;
}
- /** \copydoc _setCacheLifetime */
+
+ /** Set the cacheLifetime().
+ \param t in seconds */
void setCacheLifetime(float t) {
+ mutex.lock();
instance()._setCacheLifetime(t);
+ mutex.unlock();
}
- /** \copydoc _cacheLifetime */
+ /** 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() {
- return instance()._cacheLifetime();
+ mutex.lock();
+ float f = instance()._cacheLifetime();
+ mutex.unlock();
+ return f;
}
- /** \copydoc _createDirectory */
+
+ /** 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();
}
- /** \copydoc _currentDirectory */
+
+ /** The current working directory (cwd). Only ends in a slash if this is the root of the file system. */
static std::string currentDirectory() {
- return instance()._currentDirectory();
+ mutex.lock();
+ const std::string& s = instance()._currentDirectory();
+ mutex.unlock();
+ return s;
}
- /** \copydoc _copyFile */
+
+ /**
+ \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();
}
- /** \copydoc _exists */
- static bool exists(const std::string& f, bool trustCache = true) {
- return instance()._exists(f, trustCache);
+
+
+ /** 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;
}
- /** \copydoc _isDirectory */
+
+ /** Known bug: does not work inside zipfiles */
static bool isDirectory(const std::string& path) {
- return instance()._isDirectory(path);
+ mutex.lock();
+ bool b = instance()._isDirectory(path);
+ mutex.unlock();
+ return b;
}
- /** \copydoc _isFile */
+
+ /** Known bug: does not work inside zipfiles */
static bool isFile(const std::string& path) {
- return instance()._isFile(path);
+ mutex.lock();
+ bool b = instance()._isFile(path);
+ mutex.unlock();
+ return b;
}
- /** \copydoc _resolve */
+
+ /** 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()) {
- return instance()._resolve(path, cwd);
+ mutex.lock();
+ const std::string& s = instance()._resolve(path, cwd);
+ mutex.unlock();
+ return s;
}
- /** \copydoc _isNewer */
+
+ /** 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) {
- return instance()._isNewer(src, dst);
+ mutex.lock();
+ bool b = instance()._isNewer(src, dst);
+ mutex.unlock();
+ return b;
}
- /** \copydoc _size */
+
+ /** Returns the length of the file in bytes, or -1 if the file could not be opened. */
static int64 size(const std::string& path) {
- return instance()._size(path);
+ mutex.lock();
+ int64 i = instance()._size(path);
+ mutex.unlock();
+ return i;
}
- /** \copydoc _list */
+
+ /** 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()) {
- return instance()._list(spec, result, listSettings);
+ mutex.lock();
+ instance()._list(spec, result, listSettings);
+ mutex.unlock();
}
- /** \copydoc _getFiles */
+
+ /** list() files */
static void getFiles(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
- return instance()._getFiles(spec, result, includeParentPath);
+ mutex.lock();
+ instance()._getFiles(spec, result, includeParentPath);
+ mutex.unlock();
}
- /** \copydoc getDirectories */
+
+ /** list() directories */
static void getDirectories(const std::string& spec, Array<std::string>& result, bool includeParentPath = false) {
- return instance()._getDirectories(spec, result, includeParentPath);
+ 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();
};
@@ -400,6 +529,11 @@ 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 */
@@ -423,6 +557,11 @@ public:
/** 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.
@@ -454,11 +593,13 @@ public:
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
diff --git a/dep/g3dlite/include/G3D/Frustum.h b/dep/g3dlite/include/G3D/Frustum.h
new file mode 100644
index 00000000000..6c2d2a41303
--- /dev/null
+++ b/dep/g3dlite/include/G3D/Frustum.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/G3D.h b/dep/g3dlite/include/G3D/G3D.h
index 082d6434842..09a89b8b88d 100644
--- a/dep/g3dlite/include/G3D/G3D.h
+++ b/dep/g3dlite/include/G3D/G3D.h
@@ -1,22 +1,23 @@
/**
- @file G3D.h
+ \file G3D.h
This header includes all of the G3D libraries in
appropriate namespaces.
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-25
- @edited 2010-03-20
+ \created 2001-08-25
+ \edited 2013-03-24
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_G3D_h
#define G3D_G3D_h
-
-#define NOMINMAX 1
+#ifndef NOMINMAX
+ #define NOMINMAX 1
+#endif
#ifdef min
#undef min
#endif
@@ -24,18 +25,30 @@
#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"
@@ -43,6 +56,7 @@
#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"
@@ -53,6 +67,7 @@
#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"
@@ -61,6 +76,7 @@
#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"
@@ -68,6 +84,10 @@
#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"
@@ -75,14 +95,19 @@
#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< G3D::ReferenceCountedPointer<T> > {
- static size_t hashCode(G3D::ReferenceCountedPointer<T> key) { return reinterpret_cast<size_t>( key.pointer() ); }
+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/GImage.h"
+#include "G3D/Image.h"
#include "G3D/CollisionDetection.h"
#include "G3D/Intersect.h"
#include "G3D/Log.h"
@@ -98,18 +123,14 @@ template<class T> struct HashTrait< G3D::ReferenceCountedPointer<T> > {
#include "G3D/Capsule.h"
#include "G3D/Cylinder.h"
#include "G3D/Triangle.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/Vector2int16.h"
-#include "G3D/Vector3int16.h"
-#include "G3D/Vector3int32.h"
-#include "G3D/Vector4int8.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/GCamera.h"
-#include "G3D/GLight.h"
#include "G3D/KDTree.h"
#include "G3D/PointKDTree.h"
#include "G3D/TextOutput.h"
@@ -124,40 +145,82 @@ template<class T> struct HashTrait< G3D::ReferenceCountedPointer<T> > {
#include "G3D/PointHashGrid.h"
#include "G3D/Map2D.h"
#include "G3D/Image1.h"
-#include "G3D/Image1uint8.h"
+#include "G3D/Image1unorm8.h"
#include "G3D/Image3.h"
-#include "G3D/Image3uint8.h"
+#include "G3D/Image3unorm8.h"
#include "G3D/Image4.h"
-#include "G3D/Image4uint8.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, "zlib")
-# pragma comment(lib, "ws2_32")
# 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, "version")
# pragma comment(lib, "advapi32")
-# pragma comment(lib, "png")
-# pragma comment(lib, "jpeg")
-# pragma comment(lib, "zip")
-# ifdef _DEBUG
- // Don't link against G3D when building G3D itself.
-# ifndef G3D_BUILDING_LIBRARY_DLL
-# pragma comment(lib, "G3Dd.lib")
-# endif
+# 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
- // Don't link against G3D when building G3D itself.
-# ifndef G3D_BUILDING_LIBRARY_DLL
-# pragma comment(lib, "G3D.lib")
-# endif
+# 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
diff --git a/dep/g3dlite/include/G3D/G3DGameUnits.h b/dep/g3dlite/include/G3D/G3DGameUnits.h
index e2bc2c811e8..a53819f6b3d 100644
--- a/dep/g3dlite/include/G3D/G3DGameUnits.h
+++ b/dep/g3dlite/include/G3D/G3DGameUnits.h
@@ -3,7 +3,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2002-10-05
- @edited 2006-11-10
+ @edited 2012-02-19
*/
#ifndef G3D_GAMEUNITS_H
@@ -12,14 +12,17 @@
#include "G3D/platform.h"
namespace G3D {
+
+/** \deprecated use SimTime */
+typedef double GameTime;
+
/**
Time, in seconds.
*/
-typedef double GameTime;
typedef double SimTime;
/**
- Actual wall clock time in seconds.
+ Actual wall clock time in seconds (Unix time).
*/
typedef double RealTime;
diff --git a/dep/g3dlite/include/G3D/GCamera.h b/dep/g3dlite/include/G3D/GCamera.h
deleted file mode 100644
index 1b7b2511b43..00000000000
--- a/dep/g3dlite/include/G3D/GCamera.h
+++ /dev/null
@@ -1,354 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/GImage.h b/dep/g3dlite/include/G3D/GImage.h
deleted file mode 100644
index 9a6851d32b3..00000000000
--- a/dep/g3dlite/include/G3D/GImage.h
+++ /dev/null
@@ -1,611 +0,0 @@
-/**
- \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
diff --git a/dep/g3dlite/include/G3D/GLight.h b/dep/g3dlite/include/G3D/GLight.h
deleted file mode 100644
index 48e017d365d..00000000000
--- a/dep/g3dlite/include/G3D/GLight.h
+++ /dev/null
@@ -1,113 +0,0 @@
-/**
- @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
-
diff --git a/dep/g3dlite/include/G3D/GMutex.h b/dep/g3dlite/include/G3D/GMutex.h
index 9fe098d10e3..5676aa4584f 100644
--- a/dep/g3dlite/include/G3D/GMutex.h
+++ b/dep/g3dlite/include/G3D/GMutex.h
@@ -1,8 +1,8 @@
/**
- @file GMutex.h
+ \file G3D/GMutex.h
- @created 2005-09-22
- @edited 2009-03-25
+ \created 2005-09-22
+ \edited 2013-04-03
*/
#ifndef G3D_GMutex_h
@@ -13,10 +13,13 @@
#include "G3D/debugAssert.h"
#include <string>
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
# include <pthread.h>
# include <signal.h>
-# include <unistd.h>
+#endif
+
+#if defined(G3D_LINUX) || defined(G3D_OSX)
+# include <unistd.h> // For usleep
#endif
@@ -26,7 +29,7 @@ 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.
+ a Spinlock may be substantially faster than a mutex.
\sa G3D::GThread, G3D::GMutex, G3D::AtomicInt32
*/
@@ -41,12 +44,16 @@ public:
/** Busy waits until the lock is unlocked, then locks it
exclusively. Returns true if the lock succeeded on the first
- try (indicating no contention). */
+ 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_WIN32
+# ifdef G3D_WINDOWS
Sleep(0);
# else
usleep(0);
@@ -68,7 +75,7 @@ public:
*/
class GMutex {
private:
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
CRITICAL_SECTION m_handle;
# else
pthread_mutex_t m_handle;
diff --git a/dep/g3dlite/include/G3D/GThread.h b/dep/g3dlite/include/G3D/GThread.h
index 58437efc3fb..8670fef4e76 100644
--- a/dep/g3dlite/include/G3D/GThread.h
+++ b/dep/g3dlite/include/G3D/GThread.h
@@ -2,18 +2,21 @@
@file GThread.h
@created 2005-09-22
- @edited 2007-01-31
+ @edited 2010-09-10
*/
-#ifndef G3D_GTHREAD_H
-#define G3D_GTHREAD_H
+#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_WIN32
+#ifndef G3D_WINDOWS
# include <pthread.h>
# include <signal.h>
#endif
@@ -21,7 +24,9 @@
namespace G3D {
-typedef ReferenceCountedPointer<class GThread> GThreadRef;
+typedef shared_ptr<class GThread> GThreadRef;
+
+
/**
Platform independent thread implementation. You can either subclass and
@@ -32,11 +37,11 @@ typedef ReferenceCountedPointer<class GThread> GThreadRef;
dropping all pointers (and causing deallocation) of a GThread does NOT
stop the underlying process.
- @sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32
+ \sa G3D::GMutex, G3D::Spinlock, G3D::AtomicInt32, G3D::ThreadSet
*/
class GThread : public ReferenceCountedObject {
private:
- // "Status" is a reserved work on FreeBSD
+ // "Status" is a reserved word on FreeBSD
enum GStatus {STATUS_CREATED, STATUS_STARTED, STATUS_RUNNING, STATUS_COMPLETED};
// Not implemented on purpose, don't use
@@ -44,21 +49,21 @@ private:
GThread& operator=(const GThread&);
bool operator==(const GThread&);
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
static DWORD WINAPI internalThreadProc(LPVOID param);
#else
static void* internalThreadProc(void* param);
-#endif //G3D_WIN32
+#endif //G3D_WINDOWS
volatile GStatus m_status;
// Thread handle to hold HANDLE and pthread_t
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
HANDLE m_handle;
HANDLE m_event;
#else
pthread_t m_handle;
-#endif //G3D_WIN32
+#endif //G3D_WINDOWS
std::string m_name;
@@ -68,8 +73,11 @@ protected:
virtual void threadMain() = 0;
public:
- typedef ReferenceCountedPointer<class GThread> Ref;
- enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD};
+
+ /** 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);
@@ -110,12 +118,153 @@ public:
void waitForCompletion();
/** Returns thread name */
- inline const std::string& 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
diff --git a/dep/g3dlite/include/G3D/GUniqueID.h b/dep/g3dlite/include/G3D/GUniqueID.h
index c8b775c2e66..84204b945e7 100644
--- a/dep/g3dlite/include/G3D/GUniqueID.h
+++ b/dep/g3dlite/include/G3D/GUniqueID.h
@@ -1,16 +1,18 @@
/**
- @file GUniqueID.h
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \file G3D/GUniqueID.h
+ \author Morgan McGuire, http://graphics.cs.williams.edu
*/
-#ifndef G3D_GUNIQUEID_H
-#define G3D_GUNIQUEID_H
+#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.
@@ -25,8 +27,27 @@ private:
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;
}
@@ -37,7 +58,7 @@ public:
operator uint64() const {
return id;
- }
+ }
bool operator==(const GUniqueID& other) const {
return id == other.id;
diff --git a/dep/g3dlite/include/G3D/HashTrait.h b/dep/g3dlite/include/G3D/HashTrait.h
index 72de3da52fd..1de3777baec 100644
--- a/dep/g3dlite/include/G3D/HashTrait.h
+++ b/dep/g3dlite/include/G3D/HashTrait.h
@@ -1,11 +1,11 @@
/**
- @file HashTrait.h
+ \file G3D/HashTrait.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-10-01
- @edited 2009-11-01
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2008-10-01
+ \edited 2011-06-09
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -16,6 +16,88 @@
#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.
@@ -23,14 +105,19 @@
template <typename T> struct HashTrait{};
template <typename T> struct HashTrait<T*> {
- static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k); }
+ static size_t hashCode(const void* k) { return reinterpret_cast<size_t>(k) >> 1; }
};
-#if 0
-template <> struct HashTrait <int> {
- static size_t hashCode(int k) { return static_cast<size_t>(k); }
+/** 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
+ }
};
-#endif
template <> struct HashTrait <G3D::int16> {
static size_t hashCode(G3D::int16 k) { return static_cast<size_t>(k); }
@@ -40,10 +127,6 @@ template <> struct HashTrait <G3D::uint16> {
static size_t hashCode(G3D::uint16 k) { return static_cast<size_t>(k); }
};
-//template <> struct HashTrait <int> {
-// static size_t hashCode(int 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); }
};
@@ -58,21 +141,30 @@ template <> struct HashTrait <long unsigned int> {
};
#endif
-template <> struct HashTrait <G3D::int64> {
- static size_t hashCode(G3D::int64 k) { return static_cast<size_t>(k); }
-};
template <> struct HashTrait <G3D::uint64> {
- static size_t hashCode(G3D::uint64 k) { return static_cast<size_t>(k); }
+ 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 static_cast<size_t>(G3D::Crypto::crc32(k.c_str(), k.size())); }
+ 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> {
- // Use the FNV-1 hash (http://isthe.com/chongo/tech/comp/fnv/#FNV-1).
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);
@@ -83,9 +175,10 @@ template <> struct HashTrait<G3D::uint128> {
hash ^= (mask & key);
key >>= 8;
}
-
+
G3D::uint64 foldedHash = hash.hi ^ hash.lo;
return static_cast<size_t>((foldedHash >> 32) ^ (foldedHash & 0xFFFFFFFF));
+#endif
}
};
diff --git a/dep/g3dlite/include/G3D/Image1.h b/dep/g3dlite/include/G3D/Image1.h
index 711e83f2079..615c0a8e224 100644
--- a/dep/g3dlite/include/G3D/Image1.h
+++ b/dep/g3dlite/include/G3D/Image1.h
@@ -1,35 +1,34 @@
/**
- @file Image1.h
+ \file G3D/Image1.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2007-01-31
+ \created 2007-01-31
+ \edited 2011-08-31
*/
-#ifndef G3D_IMAGE1_H
-#define G3D_IMAGE1_H
+#ifndef G3D_Image1_h
+#define G3D_Image1_h
#include "G3D/platform.h"
#include "G3D/Map2D.h"
#include "G3D/Color1.h"
-#include "G3D/GImage.h"
namespace G3D {
-typedef ReferenceCountedPointer<class Image1> Image1Ref;
+typedef shared_ptr<class Image1> Image1Ref;
/**
Luminance image with 32-bit floating point storage.
- See also G3D::Image1uint8, G3D::GImage.
+ See also G3D::Image1unorm8, G3D::GImage.
*/
class Image1 : public Map2D<Color1, Color1> {
public:
typedef Image1 Type;
- typedef ReferenceCountedPointer<class Image1> Ref;
+ typedef shared_ptr<class Image1> Ref;
typedef Color1 Storage;
typedef Color1 Compute;
@@ -41,9 +40,9 @@ protected:
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);
+ 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:
@@ -55,25 +54,28 @@ public:
/** 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 fromFile(const std::string& filename, 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 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 fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im);
+ static Ref fromImage1unorm8(const shared_ptr<class Image1unorm8>& im);
- static Ref fromGImage(const class GImage& im, WrapMode wrap = WrapMode::ERROR);
+ /** Loads from any of the file formats supported by G3D::Image.
- /** 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);
+ 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::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
+ /** 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
diff --git a/dep/g3dlite/include/G3D/Image1uint8.h b/dep/g3dlite/include/G3D/Image1uint8.h
deleted file mode 100644
index f32e022e92a..00000000000
--- a/dep/g3dlite/include/G3D/Image1uint8.h
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/Image3.h b/dep/g3dlite/include/G3D/Image3.h
index 13cb8fa7faf..55b8e4c8742 100644
--- a/dep/g3dlite/include/G3D/Image3.h
+++ b/dep/g3dlite/include/G3D/Image3.h
@@ -1,10 +1,10 @@
/**
- @file Image3.h
+ \file G3D/Image3.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2007-01-31
+ \created 2007-01-31
+ \edited 2011-08-31
*/
@@ -14,36 +14,32 @@
#include "G3D/platform.h"
#include "G3D/Map2D.h"
#include "G3D/Color3.h"
-#include "G3D/GImage.h"
namespace G3D {
-typedef ReferenceCountedPointer<class Image3> Image3Ref;
+typedef shared_ptr<class Image3> Image3Ref;
/**
RGB image with 32-bit floating point storage for each channel.
- See also G3D::Image3uint8, G3D::GImage.
+ See also G3D::Image3unorm8, G3D::GImage.
*/
class Image3 : public Map2D<Color3, Color3> {
public:
typedef Image3 Type;
- typedef ReferenceCountedPointer<class Image3> Ref;
- typedef Color3 Storage;
- typedef Color3 Compute;
+ typedef shared_ptr<class Image3> Ref;
protected:
Image3(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);
+ 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:
@@ -55,25 +51,23 @@ public:
/** 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 fromFile(const std::string& filename, 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 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 fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im);
-
- static Ref fromGImage(const class GImage& im, 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. */
- void load(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
+ 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. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
+ /** 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
diff --git a/dep/g3dlite/include/G3D/Image3uint8.h b/dep/g3dlite/include/G3D/Image3uint8.h
deleted file mode 100644
index d4fdbc169ca..00000000000
--- a/dep/g3dlite/include/G3D/Image3uint8.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/Image4.h b/dep/g3dlite/include/G3D/Image4.h
index 21d7f1e79b1..95e96d484ce 100644
--- a/dep/g3dlite/include/G3D/Image4.h
+++ b/dep/g3dlite/include/G3D/Image4.h
@@ -1,24 +1,23 @@
/**
- @file Image4.h
+ \file G3D/Image4.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2007-01-31
+ \created 2007-01-31
+ \edited 2011-08-11
*/
-#ifndef G3D_IMAGE4_H
-#define G3D_IMAGE4_H
+#ifndef G3D_Image4_h
+#define G3D_Image4_h
#include "G3D/platform.h"
#include "G3D/Map2D.h"
#include "G3D/Color4.h"
-#include "G3D/GImage.h"
namespace G3D {
-typedef ReferenceCountedPointer<class Image4> Image4Ref;
+typedef shared_ptr<class Image4> Image4Ref;
/**
RGBA image with 32-bit floating point storage for each channel.
@@ -26,30 +25,27 @@ typedef ReferenceCountedPointer<class Image4> Image4Ref;
Whenever a method needs to convert from RGB to RGBA, A=1 is assumed.
Bilinear interpolation on Image4 is about 8x faster than on
- Image4uint8 due to the large cost of converting int->float on modern
+ Image4unorm8 due to the large cost of converting int->float on modern
machines.
- @sa G3D::Image4uint8, G3D::GImage.
+ @sa G3D::Image4unorm8, G3D::GImage.
*/
class Image4 : public Map2D<Color4, Color4> {
public:
typedef Image4 Type;
- typedef ReferenceCountedPointer<class Image4> Ref;
- typedef Color4 Storage;
- typedef Color4 Compute;
+ typedef shared_ptr<class Image4> Ref;
protected:
Image4(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);
+ 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:
@@ -61,24 +57,22 @@ public:
/** 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 fromFile(const std::string& filename, 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 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 fromImage4uint8(const ReferenceCountedPointer<class Image4uint8>& im);
-
- static Ref fromGImage(const class GImage& im, 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, GImage::Format fmt = GImage::AUTODETECT);
+ void load(const std::string& filename);
/** Saves in any of the formats supported by G3D::GImage. */
- void save(const std::string& filename, GImage::Format fmt = GImage::AUTODETECT);
+ void save(const std::string& filename);
};
} // G3D
diff --git a/dep/g3dlite/include/G3D/Image4uint8.h b/dep/g3dlite/include/G3D/Image4uint8.h
deleted file mode 100644
index 46df6b490b4..00000000000
--- a/dep/g3dlite/include/G3D/Image4uint8.h
+++ /dev/null
@@ -1,85 +0,0 @@
-/**
- @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
diff --git a/dep/g3dlite/include/G3D/ImageFormat.h b/dep/g3dlite/include/G3D/ImageFormat.h
index 15d2564330f..27a9f9443e8 100644
--- a/dep/g3dlite/include/G3D/ImageFormat.h
+++ b/dep/g3dlite/include/G3D/ImageFormat.h
@@ -1,14 +1,14 @@
/**
- @file ImageFormat.h
+ \file G3D/ImageFormat.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-05-23
- @edited 2010-05-01
+ \created 2003-05-23
+ \edited 2013-06-06
*/
-#ifndef GLG3D_ImageFormat_H
-#define GLG3D_ImageFormat_H
+#ifndef GLG3D_ImageFormat_h
+#define GLG3D_ImageFormat_h
#include "G3D/platform.h"
#include "G3D/Table.h"
@@ -17,16 +17,22 @@
namespace G3D {
-/** Information about common image formats.
- Don't construct these; use the methods provided.
+/** 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. This does not hold for the YUV and DXT formats.*/
+ 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,
@@ -58,24 +64,57 @@ public:
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,
@@ -141,6 +180,14 @@ public:
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;
@@ -182,10 +229,6 @@ public:
/** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding. */
int cpuBitsPerPixel;
- /** Amount of CPU memory per pixel when packed into an array, discounting any end-of-row padding.
- @deprecated Use cpuBitsPerPixel*/
- int packedBitsPerTexel;
-
/**
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.
@@ -196,24 +239,38 @@ public:
*/
int openGLBitsPerPixel;
- /** @deprecated Use openGLBitsPerPixel */
- int hardwareBitsPerTexel;
-
/** 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. */
+
+ /** 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
@@ -228,11 +285,11 @@ private:
int blueBits,
int depthBits,
int stencilBits,
- int hardwareBitsPerTexel,
- int packedBitsPerTexel,
+ int openGLBitsPerPixel,
+ int cpuBitsPerPixel,
int glDataFormat,
bool opaque,
- bool floatingPoint,
+ NumberFormat numberFormat,
Code code,
ColorSpace colorSpace,
BayerPattern bayerPattern = BAYER_PATTERN_NONE);
@@ -267,14 +324,36 @@ public:
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();
@@ -299,6 +378,12 @@ public:
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();
@@ -309,8 +394,15 @@ public:
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();
@@ -359,7 +451,7 @@ public:
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.
@@ -381,7 +473,6 @@ public:
static const ImageFormat* fromCode(ImageFormat::Code code);
-
/** For use with ImageFormat::convert. */
class BayerAlgorithm {
public:
@@ -418,13 +509,48 @@ public:
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);
+ 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. */
+ /**
+ 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;
diff --git a/dep/g3dlite/include/G3D/Intersect.h b/dep/g3dlite/include/G3D/Intersect.h
index 4a3c8fb4540..cc841d65069 100644
--- a/dep/g3dlite/include/G3D/Intersect.h
+++ b/dep/g3dlite/include/G3D/Intersect.h
@@ -27,17 +27,17 @@ namespace G3D {
class Intersect {
public:
- /** \brief Returns true if the intersection of the ray and the solid box is non-empty.
+ /** \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);
+ 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.
-
+ /** \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.
@@ -47,7 +47,7 @@ public:
Computer Graphics Lab, TU Braunschweig, Germany and
University of Koblenz-Landau, Germany
*/
- static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time);
+ static bool __fastcall rayAABox(const Ray& ray, const AABox& box, float& time);
};
}
diff --git a/dep/g3dlite/include/G3D/KDTree.h b/dep/g3dlite/include/G3D/KDTree.h
index 4785ef2baea..57b54acc57d 100644
--- a/dep/g3dlite/include/G3D/KDTree.h
+++ b/dep/g3dlite/include/G3D/KDTree.h
@@ -10,8 +10,8 @@
All rights reserved.
*/
-#ifndef G3D_KDTREE_H
-#define G3D_KDTREE_H
+#ifndef G3D_KDTree_h
+#define G3D_KDTree_h
#include "G3D/platform.h"
#include "G3D/Array.h"
@@ -24,11 +24,10 @@
#include "G3D/Box.h"
#include "G3D/Triangle.h"
#include "G3D/Ray.h"
-#include "G3D/GCamera.h"
+#include "G3D/Frustum.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/CollisionDetection.h"
-#include "G3D/GCamera.h"
#include "G3D/BoundsTrait.h"
#include <algorithm>
@@ -260,11 +259,11 @@ protected:
/** Compares centers */
class CenterComparator {
public:
- Vector3::Axis sortAxis;
+ Vector3::Axis sortAxis;
- CenterComparator(Vector3::Axis a) : sortAxis(a) {}
+ CenterComparator(Vector3::Axis a) : sortAxis(a) {}
- inline int operator()(Handle* A, const Handle* B) const {
+ inline int operator()(Handle* A, const Handle* B) const {
float a = A->center[sortAxis];
float b = B->center[sortAxis];
@@ -275,18 +274,18 @@ protected:
} else {
return 0;
}
- }
+ }
};
/** Compares bounds for strict >, <, or overlap*/
class BoundsComparator {
public:
- Vector3::Axis sortAxis;
+ Vector3::Axis sortAxis;
- BoundsComparator(Vector3::Axis a) : sortAxis(a) {}
+ BoundsComparator(Vector3::Axis a) : sortAxis(a) {}
- inline int operator()(Handle* A, const Handle* B) const {
+ inline int operator()(Handle* A, const Handle* B) const {
const AABox& a = A->bounds;
const AABox& b = B->bounds;
@@ -297,34 +296,34 @@ protected:
} else {
return 0;
}
- }
+ }
};
/** Compares bounds to the sort location */
class Comparator {
public:
- Vector3::Axis sortAxis;
- float sortLocation;
+ Vector3::Axis sortAxis;
+ float sortLocation;
- Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {}
+ Comparator(Vector3::Axis a, float l) : sortAxis(a), sortLocation(l) {}
- inline int operator()(Handle* ignore, const Handle* handle) const {
+ inline int operator()(Handle* ignore, const Handle* handle) const {
(void)ignore;
const AABox& box = handle->bounds;
debugAssert(ignore == NULL);
- if (box.high()[sortAxis] < sortLocation) {
+ if (box.high()[sortAxis] < sortLocation) {
// Box is strictly below the sort location
return -1;
- } else if (box.low()[sortAxis] > sortLocation) {
+ } else if (box.low()[sortAxis] > sortLocation) {
// Box is strictly above the sort location
- return 1;
- } else {
+ return 1;
+ } else {
// Box overlaps the sort location
- return 0;
- }
- }
+ return 0;
+ }
+ }
};
// Using System::malloc with this class provided no speed improvement.
@@ -433,8 +432,8 @@ protected:
}
void verifyNode(const Vector3& lo, const Vector3& hi) {
- // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
- // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
+ // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
+ // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
debugAssertM(lo == splitBounds.low(),
format("lo = %s, splitBounds.lo = %s",
@@ -444,6 +443,7 @@ protected:
for (int i = 0; i < valueArray.length(); ++i) {
const AABox& b = valueArray[i]->bounds;
debugAssert(b == boundsArray[i]);
+ (void)b;
for(int axis = 0; axis < 3; ++axis) {
debugAssert(b.low()[axis] <= b.high()[axis]);
@@ -714,27 +714,27 @@ protected:
int numMeanSplits,
Array<Handle*>& temp) {
- Node* node = NULL;
-
- if (source.size() <= valuesPerNode) {
- // Make a new leaf node
- node = new Node(source);
-
- // Set the pointers in the memberTable
- for (int i = 0; i < source.size(); ++i) {
- memberTable.set(Member(source[i]), node);
- }
+ Node* node = NULL;
+
+ if (source.size() <= valuesPerNode) {
+ // Make a new leaf node
+ node = new Node(source);
+
+ // Set the pointers in the memberTable
+ for (int i = 0; i < source.size(); ++i) {
+ memberTable.set(Member(source[i]), node);
+ }
source.clear();
-
+
} else {
- // Make a new internal node
- node = new Node();
-
+ // Make a new internal node
+ node = new Node();
+
const AABox& bounds = computeBounds(source, 0, source.size() - 1);
- const Vector3& extent = bounds.high() - bounds.low();
-
- Vector3::Axis splitAxis = extent.primaryAxis();
-
+ const Vector3& extent = bounds.high() - bounds.low();
+
+ Vector3::Axis splitAxis = extent.primaryAxis();
+
float splitLocation;
// Arrays for holding the children
@@ -829,20 +829,20 @@ protected:
for (int i = 0; i < node->valueArray.size(); ++i) {
Handle* v = node->valueArray[i];
node->boundsArray[i] = v->bounds;
- memberTable.set(Member(v), node);
+ memberTable.set(Member(v), node);
}
- if (lt.size() > 0) {
- node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
- }
-
- if (gt.size() > 0) {
- node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
- }
-
- }
-
- return node;
+ if (lt.size() > 0) {
+ node->child[0] = makeNode(lt, valuesPerNode, numMeanSplits - 1, temp);
+ }
+
+ if (gt.size() > 0) {
+ node->child[1] = makeNode(gt, valuesPerNode, numMeanSplits - 1, temp);
+ }
+
+ }
+
+ return node;
}
/**
@@ -1211,7 +1211,7 @@ public:
/**
Typically used to find all visible
- objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
+ objects inside the view frustum (see also Camera::getClipPlanes)... i.e. all objects
<B>not</B> culled by frustum.
Example:
@@ -1222,7 +1222,7 @@ public:
</PRE>
@param members The results are appended to this array.
*/
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T*>& members) const {
+ void getIntersectingMembers(const Frustum& frustum, Array<T*>& members) const {
Array<Plane> plane;
for (int i = 0; i < frustum.faceArray.size(); ++i) {
@@ -1232,7 +1232,7 @@ public:
getIntersectingMembers(plane, members);
}
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
+ void getIntersectingMembers(const Frustum& frustum, Array<T>& members) const {
Array<T*> temp;
getIntersectingMembers(frustum, temp);
for (int i = 0; i < temp.size(); ++i) {
@@ -1450,49 +1450,50 @@ public:
/**
Invoke a callback for every member along a ray until the closest intersection is found.
- @param callback either a function or an instance of a class with an overloaded operator() of the form:
-
- <code>void callback(const Ray& ray, const T& object, float& distance)</code>. If the ray hits the object
- before travelling distance <code>distance</code>, updates <code>distance</code> with the new distance to
- the intersection, otherwise leaves it unmodified. A common example is:
-
+ @param intersectCallback Either a function or an instance of a class with an overloaded operator() of the form:
+ <pre>
+ void callback(const Ray& ray, const T& object, float& distance).
+ </pre>
+ If the ray hits the object before travelling distance <code>distance</code>, updates
+ <code>distance</code> with the new distance to the intersection, otherwise leaves it
+ unmodified. A common example is:
+ \htmlonly
<pre>
class Entity {
public:
-
- void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
- float d = maxDist;
-
- // ... search for intersection distance d
-
- if ((d > 0) && (d < maxDist)) {
- // Intersection occured
- maxDist = d;
- outLocation = ...;
- outNormal = ...;
- }
- }
- };
-
- // Finds the surface normal and location of the first intersection with the scene
- class Intersection {
- public:
- Entity* closestEntity;
- Vector3 hitLocation;
- Vector3 hitNormal;
-
- void operator()(const Ray& ray, const Entity* entity, float& distance) {
- entity->intersect(ray, distance, hitLocation, hitNormal);
- }
- };
-
- KDTree<Entity*> scene;
-
- Intersection intersection;
- float distance = finf();
- scene.intersectRay(camera.worldRay(x, y), intersection, distance);
- </pre>
-
+ void intersect(const Ray& ray, float& maxDist, Vector3& outLocation, Vector3& outNormal) {
+ float d = maxDist;
+
+ // ... search for intersection distance d
+
+ if ((d > 0) && (d < maxDist)) {
+ // Intersection occured
+ maxDist = d;
+ outLocation = ...;
+ outNormal = ...;
+ }
+ }
+ };
+
+ // Finds the surface normal and location of the first intersection with the scene
+ class Intersection {
+ public:
+ Entity* closestEntity;
+ Vector3 hitLocation;
+ Vector3 hitNormal;
+
+ void operator()(const Ray& ray, const Entity* entity, float& distance) {
+ entity->intersect(ray, distance, hitLocation, hitNormal);
+ }
+ };
+
+ KDTree<Entity*> scene;
+
+ Intersection intersection;
+ float distance = finf();
+ scene.intersectRay(camera.worldRay(x, y), intersection, distance);
+ </pre>
+ \endhtmlonly
@param distance When the method is invoked, this is the maximum
distance that the tree should search for an intersection. On
diff --git a/dep/g3dlite/include/G3D/Line.h b/dep/g3dlite/include/G3D/Line.h
index 3579a6becec..2686474c4b7 100644
--- a/dep/g3dlite/include/G3D/Line.h
+++ b/dep/g3dlite/include/G3D/Line.h
@@ -38,11 +38,11 @@ public:
/** Undefined (provided for creating Array<Line> only) */
inline Line() {}
- Line(class BinaryInput& b);
+ Line(class BinaryInput& b);
- void serialize(class BinaryOutput& b) const;
+ void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
+ void deserialize(class BinaryInput& b);
virtual ~Line() {}
diff --git a/dep/g3dlite/include/G3D/LineSegment.h b/dep/g3dlite/include/G3D/LineSegment.h
index 70210ec7e00..9d3b7e3d30c 100644
--- a/dep/g3dlite/include/G3D/LineSegment.h
+++ b/dep/g3dlite/include/G3D/LineSegment.h
@@ -21,35 +21,39 @@ namespace G3D {
class LineSegment {
protected:
- Vector3 _point;
+ Point3 _point;
/** Not normalized */
Vector3 direction;
- LineSegment(const Vector3& __point, const Vector3& _direction) : _point(__point), direction(_direction) {
+ LineSegment(const Point3& __point, const Vector3& _direction) : _point(__point), direction(_direction) {
}
public:
- inline LineSegment() : _point(Vector3::zero()), direction(Vector3::zero()) {}
+ LineSegment() : _point(Point3::zero()), direction(Vector3::zero()) {}
- LineSegment(class BinaryInput& b);
-
- void serialize(class BinaryOutput& b) const;
-
- void deserialize(class BinaryInput& b);
+ 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 Vector3 &point1, const Vector3 &point2) {
+ static LineSegment fromTwoPoints(const Point3 &point1, const Point3 &point2) {
return LineSegment(point1, point2 - point1);
}
- /** Call with 0 or 1 */
- Vector3 point(int i) const;
+ /** 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();
@@ -58,23 +62,23 @@ public:
/**
* Returns the closest point on the line segment to point.
*/
- Vector3 closestPoint(const Vector3 &point) const;
+ Point3 closestPoint(const Point3 &point) const;
/**
Returns the distance between point and the line
*/
- double distance(const Vector3& p) const {
+ double distance(const Point3& p) const {
return (closestPoint(p) - p).magnitude();
}
- double distanceSquared(const Vector3& p) const {
+ 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;
- Vector3 randomPoint() const;
+ Point3 randomPoint() const;
};
@@ -82,7 +86,7 @@ public:
class LineSegment2D {
private:
- Vector2 m_origin;
+ Point2 m_origin;
/** Not normalized */
Vector2 m_direction;
@@ -94,17 +98,17 @@ public:
LineSegment2D() {}
- static LineSegment2D fromTwoPoints(const Vector2& p0, const Vector2& p1);
+ static LineSegment2D fromTwoPoints(const Point2& p0, const Vector2& p1);
/** Returns the intersection of these segements (including
- testing endpoints), or Vector2::inf() if they do not intersect. */
- Vector2 intersection(const LineSegment2D& other) const;
+ testing endpoints), or Point2::inf() if they do not intersect. */
+ Point2 intersection(const LineSegment2D& other) const;
- Vector2 point(int i) const;
+ Point2 point(int i) const;
- Vector2 closestPoint(const Vector2& Q) const;
+ Point2 closestPoint(const Point2& Q) const;
- float distance(const Vector2& p) const;
+ float distance(const Point2& p) const;
float length() const;
};
diff --git a/dep/g3dlite/include/G3D/Log.h b/dep/g3dlite/include/G3D/Log.h
index d252d0c1a17..2aedb13dcdc 100644
--- a/dep/g3dlite/include/G3D/Log.h
+++ b/dep/g3dlite/include/G3D/Log.h
@@ -14,7 +14,7 @@
#include <string>
#include "G3D/platform.h"
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
#include <stdarg.h>
#endif
diff --git a/dep/g3dlite/include/G3D/Map2D.h b/dep/g3dlite/include/G3D/Map2D.h
index 9af9f7242c1..ec44c7ed969 100644
--- a/dep/g3dlite/include/G3D/Map2D.h
+++ b/dep/g3dlite/include/G3D/Map2D.h
@@ -87,7 +87,7 @@ namespace G3D {
G3D::GImage - Supports file formats, fast, Color3uint8 and Color4uint8 formats. No interpolation.
- G3D::Texture::Ref - 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::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.
@@ -181,7 +181,7 @@ public:
typedef Storage StorageType;
typedef Compute ComputeType;
typedef Map2D<Storage, Compute> Type;
- typedef ReferenceCountedPointer<Map2D> Ref;
+ typedef shared_ptr<Map2D> Ref;
protected:
@@ -296,7 +296,7 @@ public:
GMutex mutex;
static Ref create(int w = 0, int h = 0, WrapMode wrap = WrapMode::ERROR) {
- return new Map2D(w, h, wrap);
+ return Ref(new Map2D(w, h, wrap));
}
/** Resizes without clearing, leaving garbage.
@@ -372,7 +372,7 @@ public:
// (we're returning a const reference so this is ok)
return const_cast<Type*>(this)->slowGet(x, y, wrap);
}
-# ifndef G3D_WIN32
+# 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;
@@ -393,7 +393,7 @@ public:
inline Storage& get(int x, int y, WrapMode wrap) {
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y, wrap));
-# ifndef G3D_WIN32
+# 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;
@@ -402,7 +402,7 @@ public:
inline Storage& get(int x, int y) {
return const_cast<Storage&>(const_cast<const Type*>(this)->get(x, y));
-# ifndef G3D_WIN32
+# 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;
@@ -441,6 +441,19 @@ public:
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) {
@@ -448,38 +461,38 @@ public:
}
}
- 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;
- }
- }
+ 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;
- }
- }
+ }
+
+ 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.
*/
diff --git a/dep/g3dlite/include/G3D/Matrix.h b/dep/g3dlite/include/G3D/Matrix.h
index 3c5394d9a76..3293a31a3f1 100644
--- a/dep/g3dlite/include/G3D/Matrix.h
+++ b/dep/g3dlite/include/G3D/Matrix.h
@@ -234,7 +234,7 @@ public:
};
private:
- typedef ReferenceCountedPointer<Impl> ImplRef;
+ typedef shared_ptr<Impl> ImplRef;
ImplRef impl;
@@ -501,10 +501,13 @@ public:
}
/**
- (A<SUP>T</SUP>A)<SUP>-1</SUP>A<SUP>T</SUP>) computed
- using SVD.
+ \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
- @param tolerance Use -1 for automatic tolerance.
+ \cite http://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse
+
+ \param tolerance Use -1 for automatic tolerance.
*/
Matrix pseudoInverse(float tolerance = -1) const;
@@ -576,7 +579,7 @@ public:
/** Serializes in Matlab source format */
void serialize(TextOutput& t) const;
- std::string toString(const std::string& name) const;
+ std::string toString(const std::string& name) const;
std::string toString() const {
static const std::string name = "";
diff --git a/dep/g3dlite/include/G3D/Matrix2.h b/dep/g3dlite/include/G3D/Matrix2.h
index cab70c83e44..bfae26e9de1 100644
--- a/dep/g3dlite/include/G3D/Matrix2.h
+++ b/dep/g3dlite/include/G3D/Matrix2.h
@@ -9,7 +9,7 @@ namespace G3D {
/** @beta */
class Matrix2 {
private:
-
+ // Row, column
float data[2][2];
public:
@@ -57,14 +57,22 @@ public:
data[1][0] / f, data[1][1] / f);
}
- float* operator[](int i) {
- debugAssert(i >= 0 && i <= 2);
- return data[i];
+ inline float* operator[] (int i) {
+ debugAssert(i >= 0 && i <= 1);
+ return (float*)&data[i][0];
}
- const float* operator[](int i) const {
+ inline const float* operator[] (int i) const {
debugAssert(i >= 0 && i <= 1);
- return data[i];
+ 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];
}
};
diff --git a/dep/g3dlite/include/G3D/Matrix3.h b/dep/g3dlite/include/G3D/Matrix3.h
index 06ec7e67474..8cfcfe9599f 100644
--- a/dep/g3dlite/include/G3D/Matrix3.h
+++ b/dep/g3dlite/include/G3D/Matrix3.h
@@ -1,14 +1,14 @@
/**
- @file Matrix3.h
+ \file Matrix3.h
3x3 matrix class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \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>
+ \cite Portions based on Dave Eberly's Magic Software Library at <A HREF="http://www.magic-software.com">http://www.magic-software.com</A>
- @created 2001-06-02
- @edited 2006-04-05
+ \created 2001-06-02
+ \edited 2011-05-05
*/
#ifndef G3D_Matrix3_h
@@ -32,11 +32,12 @@ namespace G3D {
class Any;
/**
- 3x3 matrix. Do not subclass.
+ A 3x3 matrix. Do not subclass. Data is unitializd when default constructed.
*/
class Matrix3 {
private:
+ // Row, column
float elt[3][3];
// Hidden operators
@@ -47,13 +48,39 @@ private:
public:
+ /** Must be in one of the following forms:
+ - Matrix3(#, #, # .... #)
+ - Matrix3::fromAxisAngle(#, #)
+ - Matrix3::diagonal(#, #, #)
+ - Matrix3::identity()
+ */
Matrix3(const Any& any);
- operator Any() const;
+ 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;
+ }
- /** Initial values are undefined for performance. See also
- Matrix3::zero(), Matrix3::identity(), Matrix3::fromAxisAngle, etc.*/
- inline Matrix3() {}
+ 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]);
@@ -62,13 +89,19 @@ public:
float fEntry10, float fEntry11, float fEntry12,
float fEntry20, float fEntry21, float fEntry22);
- bool fuzzyEq(const Matrix3& b) const;
+ 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*/
+ @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);
@@ -83,7 +116,7 @@ public:
float fEntry20, float fEntry21, float fEntry22);
/**
- * member access, allows use of construct mat[r][c]
+ Member access, allows use of construct mat[r][c]
*/
inline float* operator[] (int iRow) {
debugAssert(iRow >= 0);
@@ -267,8 +300,12 @@ public:
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
diff --git a/dep/g3dlite/include/G3D/Matrix4.h b/dep/g3dlite/include/G3D/Matrix4.h
index 6b810ba77e8..d33006a4a75 100644
--- a/dep/g3dlite/include/G3D/Matrix4.h
+++ b/dep/g3dlite/include/G3D/Matrix4.h
@@ -5,8 +5,8 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-10-02
- @edited 2009-10-20
+ \created 2003-10-02
+ \edited 2012-12-25
*/
#ifndef G3D_Matrix4_h
@@ -26,11 +26,12 @@
namespace G3D {
class Any;
+class Matrix2;
/**
- A 4x4 matrix.
+ A 4x4 matrix. Do not subclass. Data is initialized to 0 when default constructed.
- See also G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat
+ \sa G3D::CoordinateFrame, G3D::Matrix3, G3D::Quat
*/
class Matrix4 {
private:
@@ -50,10 +51,20 @@ private:
bool operator>=(const Matrix4&) const;
public:
- /** Must be of the form: <code>Matrix4(#, #, # .... #)</code>*/
- Matrix4(const Any& any);
- operator Any() const;
+ /** 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,
@@ -66,17 +77,25 @@ public:
*/
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).
- */
+ /**
+ 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. */
@@ -88,14 +107,19 @@ public:
static const Matrix4& zero();
/** If this is a perspective projection matrix created by
- Matrix4::perspectiveProjection, extract its parameters. */
+ Matrix4::perspectiveProjection, extract its parameters.
+
+ Uses double precision because the operations involved in
+ projection involve divisions that can significantly impact
+ precision.
+ */
void getPerspectiveProjectionParameters
- (float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
+ (double& left,
+ double& right,
+ double& bottom,
+ double& top,
+ double& nearval,
+ double& farval,
float updirection = -1.0f) const;
inline float* operator[](int r) {
@@ -110,6 +134,7 @@ public:
return (const float*)&elt[r];
}
+ /** Returns a row-major pointer. */
inline operator float* () {
return (float*)&elt[0][0];
}
@@ -131,6 +156,8 @@ public:
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;
@@ -151,7 +178,6 @@ public:
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)
*/
@@ -163,15 +189,18 @@ public:
/** \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(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection = -1.0f);
+ 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);
@@ -248,6 +277,67 @@ public:
};
+/** 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
diff --git a/dep/g3dlite/include/G3D/MemoryManager.h b/dep/g3dlite/include/G3D/MemoryManager.h
index 15bf6d8be43..be6f6400cb6 100644
--- a/dep/g3dlite/include/G3D/MemoryManager.h
+++ b/dep/g3dlite/include/G3D/MemoryManager.h
@@ -20,7 +20,7 @@ namespace G3D {
Abstraction of memory management.
Default implementation uses G3D::System::malloc and is threadsafe.
- \sa CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
+ \sa LargePoolMemoryManager, CRTMemoryManager, AlignedMemoryManager, AreaMemoryManager */
class MemoryManager : public ReferenceCountedObject {
protected:
@@ -28,7 +28,7 @@ protected:
public:
- typedef ReferenceCountedPointer<class MemoryManager> Ref;
+ 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
@@ -59,7 +59,7 @@ protected:
public:
- typedef ReferenceCountedPointer<class AlignedMemoryManager> Ref;
+ typedef shared_ptr<class AlignedMemoryManager> Ref;
virtual void* alloc(size_t s);
@@ -72,13 +72,14 @@ public:
};
-/** MemoryManager implemented using the C runtime. */
+/** 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 ReferenceCountedPointer<class MemoryManager> Ref;
+ typedef shared_ptr<class MemoryManager> Ref;
virtual void* alloc(size_t s);
virtual void free(void* ptr);
virtual bool isThreadsafe() const;
diff --git a/dep/g3dlite/include/G3D/MeshAlg.h b/dep/g3dlite/include/G3D/MeshAlg.h
index da55d13000a..d0cdd528b8a 100644
--- a/dep/g3dlite/include/G3D/MeshAlg.h
+++ b/dep/g3dlite/include/G3D/MeshAlg.h
@@ -20,9 +20,10 @@
#include "G3D/constants.h"
#include "G3D/Image1.h"
-#ifdef G3D_WIN32
+#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
@@ -444,7 +445,7 @@ public:
Array<Vector3>& newVertexPositions,
Array<int>& toNew,
Array<int>& toOld,
- double radius = fuzzyEpsilon);
+ float radius = fuzzyEpsilon32);
/**
Modifies the face, edge, and vertex arrays in place so that
@@ -479,7 +480,7 @@ public:
Array<Face>& faceArray,
Array<Edge>& edgeArray,
Array<Vertex>& vertexArray,
- double radius = fuzzyEpsilon);
+ float radius = fuzzyEpsilon32);
/**
@@ -535,7 +536,7 @@ public:
/**
Generates a unit square in the X-Z plane composed of a grid of wCells x hCells
- squares and then transforms it by xform.
+ squares on the unit interval and then transforms it by xform.
@param vertex Output vertices
@param texCoord Output texture coordinates
@@ -545,8 +546,8 @@ public:
@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,
+ static void generateGrid
+ (Array<Vector3>& vertex,
Array<Vector2>& texCoord,
Array<int>& index,
int wCells = 10,
@@ -555,7 +556,7 @@ public:
bool spaceCentered = true,
bool twoSided = true,
const CoordinateFrame& xform = CoordinateFrame(),
- const Image1::Ref& elevation = NULL);
+ const Image1::Ref& elevation = Image1::Ref());
/** Converts quadlist (QUADS),
triangle fan (TRIANGLE_FAN),
@@ -679,5 +680,11 @@ protected:
int i0, int i1, int f, double area);
};
}
+
+
+#ifdef G3D_WINDOWS
+#pragma warning( pop )
+#endif
+
#endif
diff --git a/dep/g3dlite/include/G3D/MeshBuilder.h b/dep/g3dlite/include/G3D/MeshBuilder.h
index 9920d59d7d3..b8a5f5bf170 100644
--- a/dep/g3dlite/include/G3D/MeshBuilder.h
+++ b/dep/g3dlite/include/G3D/MeshBuilder.h
@@ -34,6 +34,8 @@ private:
typedef Array<int> List;
std::string name;
+
+ bool scaleAndCenter;
/**
All of the triangles, as a long triangle list.
@@ -43,14 +45,14 @@ private:
void centerTriList();
void computeBounds(Vector3& min, Vector3& max);
- bool _twoSided;
+ bool _twoSided;
/** Collapse radius */
double close;
public:
- inline MeshBuilder(bool twoSided = false) : _twoSided(twoSided), close(AUTO_WELD) {}
+ 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 */
diff --git a/dep/g3dlite/include/G3D/NetAddress.h b/dep/g3dlite/include/G3D/NetAddress.h
index fd5a199593b..f4bc03f4550 100644
--- a/dep/g3dlite/include/G3D/NetAddress.h
+++ b/dep/g3dlite/include/G3D/NetAddress.h
@@ -1,3 +1,9 @@
+/**
+ \file G3D/NetAddress.h
+
+ \created 2010-01-03
+ \edited 2013-03-17
+ */
#ifndef G3D_NetAddress_h
#define G3D_NetAddress_h
@@ -24,20 +30,31 @@ private:
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
+ In host byte order.
+
+ \sa DEFAULT_ADAPTER_HOST
*/
- NetAddress(uint32 host, uint16 port = 0);
+ 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"
*/
- NetAddress(const std::string& hostnameAndPort);
+ explicit NetAddress(const std::string& hostnameAndPort);
/**
@deprecated Use G3D::NetworkDevice::broadcastAddressArray()
@@ -56,6 +73,8 @@ public:
NetAddress();
+ static void localHostAddresses(Array<NetAddress>& array);
+
void serialize(class BinaryOutput& b) const;
void deserialize(class BinaryInput& b);
@@ -76,6 +95,13 @@ public:
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&);
@@ -95,7 +121,7 @@ namespace G3D {
they have different IP's.
*/
inline bool operator==(const NetAddress& a, const NetAddress& b) {
- return (a.ip() == b.ip()) && (a.port() == b.port());
+ return (a.ip() == b.ip()) && (a.port() == b.port());
}
diff --git a/dep/g3dlite/include/G3D/NetworkDevice.h b/dep/g3dlite/include/G3D/NetworkDevice.h
index 7a3f8ed4aca..e60878cb8a2 100644
--- a/dep/g3dlite/include/G3D/NetworkDevice.h
+++ b/dep/g3dlite/include/G3D/NetworkDevice.h
@@ -1,6 +1,5 @@
/**
@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
@@ -54,7 +53,7 @@
namespace G3D {
class TextOutput;
-
+/** \deprecated */
class Conduit : public ReferenceCountedObject {
protected:
friend class NetworkDevice;
@@ -134,7 +133,7 @@ public:
bool ok() const;
};
-typedef ReferenceCountedPointer<class ReliableConduit> ReliableConduitRef;
+typedef shared_ptr<class ReliableConduit> ReliableConduitRef;
#ifdef __GNUC__
// Workaround for a known bug in gcc 4.x where htonl produces
@@ -164,7 +163,7 @@ uint32 gcchtonl(uint32);
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:
@@ -209,7 +208,7 @@ private:
// Reserve space for the 4 byte size header
b.writeUInt32(0);
- size_t L = b.length();
+ size_t L = (size_t)b.length();
m.serialize(b);
if ((size_t)b.length() == L) {
// No data was created by serialization.
@@ -218,7 +217,7 @@ private:
b.writeUInt8(0xFF);
}
- uint32 len = b.size() - 8;
+ 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
@@ -353,7 +352,7 @@ public:
};
-typedef ReferenceCountedPointer<class LightweightConduit> LightweightConduitRef;
+typedef shared_ptr<class LightweightConduit> LightweightConduitRef;
/**
Provides fast but unreliable transfer of messages. On a LAN,
@@ -402,6 +401,8 @@ and a pointer to an instance of the message you want to send.
it go out of scope and the conduit cleans itself up automatically.
</OL>
+
+\deprecated
*/
class LightweightConduit : public Conduit {
private:
@@ -458,7 +459,7 @@ private:
format("This LightweightConduit is limited to messages of "
"%d bytes (Ethernet hardware limit; this is the "
"'UDP MTU')", maxMessageSize()),
- b.size() - 4, // Don't count the type header
+ (int)b.size() - 4, // Don't count the type header
maxMessageSize());
}
}
@@ -512,13 +513,13 @@ public:
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);
- }
+ 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;
}
@@ -536,10 +537,12 @@ public:
///////////////////////////////////////////////////////////////////////////////
-typedef ReferenceCountedPointer<class NetListener> NetListenerRef;
+typedef shared_ptr<class NetListener> NetListenerRef;
/**
Runs on the server listening for clients trying to make reliable connections.
+
+ \deprecated
*/
class NetListener : public ReferenceCountedObject {
private:
@@ -600,6 +603,7 @@ public:
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:
diff --git a/dep/g3dlite/include/G3D/ParseError.h b/dep/g3dlite/include/G3D/ParseError.h
index f02948e3d29..dc423d676f1 100644
--- a/dep/g3dlite/include/G3D/ParseError.h
+++ b/dep/g3dlite/include/G3D/ParseError.h
@@ -52,6 +52,9 @@ public:
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;
};
}
diff --git a/dep/g3dlite/include/G3D/PhysicsFrame.h b/dep/g3dlite/include/G3D/PhysicsFrame.h
index 9aee5e5a883..ae36e312d2c 100644
--- a/dep/g3dlite/include/G3D/PhysicsFrame.h
+++ b/dep/g3dlite/include/G3D/PhysicsFrame.h
@@ -1,14 +1,14 @@
/**
- @file PhysicsFrame.h
+ \file PhysicsFrame.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-07-08
- @edited 2006-01-10
+ \created 2002-07-08
+ \edited 2011-05-10
*/
-#ifndef G3D_PHYSICSFRAME_H
-#define G3D_PHYSICSFRAME_H
+#ifndef G3D_PhysicsFrame_h
+#define G3D_PhysicsFrame_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -33,9 +33,9 @@ public:
Quat rotation;
/**
- Takes object space points to world space.
+ Origin of this reference frame in its parent's frame.
*/
- Vector3 translation;
+ Point3 translation;
/**
Initializes to the identity frame.
@@ -51,6 +51,13 @@ public:
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( ... )
@@ -59,6 +66,8 @@ public:
*/
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;
@@ -100,6 +109,16 @@ public:
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;
diff --git a/dep/g3dlite/include/G3D/PhysicsFrameSpline.h b/dep/g3dlite/include/G3D/PhysicsFrameSpline.h
index 4a21503df35..75d3fea8039 100644
--- a/dep/g3dlite/include/G3D/PhysicsFrameSpline.h
+++ b/dep/g3dlite/include/G3D/PhysicsFrameSpline.h
@@ -20,16 +20,31 @@ namespace G3D {
*/
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);
- /** Clear and then reset all values from the any */
- PhysicsFrameSpline& operator=(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");
+ }
};
}
diff --git a/dep/g3dlite/include/G3D/Plane.h b/dep/g3dlite/include/G3D/Plane.h
index 360bcd2bc75..4c1a2487b9d 100644
--- a/dep/g3dlite/include/G3D/Plane.h
+++ b/dep/g3dlite/include/G3D/Plane.h
@@ -1,16 +1,16 @@
/**
- @file Plane.h
+ \file Plane.h
Plane class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2004-07-18
+ \created 2001-06-02
+ \edited 2010-12-04
*/
-#ifndef G3D_PLANE_H
-#define G3D_PLANE_H
+#ifndef G3D_Plane_h
+#define G3D_Plane_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -26,8 +26,8 @@ class Plane {
private:
/** normal.Dot(x,y,z) = distance */
- Vector3 _normal;
- float _distance;
+ Vector3 _normal;
+ float _distance;
/**
Assumes the normal has unit length.
@@ -40,43 +40,51 @@ 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 Vector3& point0,
- const Vector3& point1,
- const Vector3& point2);
+ 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);
+ Vector4 point0,
+ Vector4 point1,
+ Vector4 point2);
/**
The normal will be unitized.
*/
- Plane(
- const Vector3& __normal,
- const Vector3& point);
+ 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);
+ 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(Vector3 point) const {
+ inline bool halfSpaceContains(Point3 point) const {
// Clamp to a finite range for testing
point = point.clamp(Vector3::minFinite(), Vector3::maxFinite());
@@ -101,7 +109,7 @@ public:
Returns true if point is on the side the normal points to or
is in the plane. Only call on finite points. Faster than halfSpaceContains.
*/
- inline bool halfSpaceContainsFinite(const Vector3& point) const {
+ inline bool halfSpaceContainsFinite(const Point3& point) const {
debugAssert(point.isFinite());
return _normal.dot(point) >= _distance;
}
@@ -109,13 +117,13 @@ public:
/**
Returns true if the point is nearly in the plane.
*/
- inline bool fuzzyContains(const Vector3 &point) const {
+ inline bool fuzzyContains(const Point3& point) const {
return fuzzyEq(point.dot(_normal), _distance);
}
- inline const Vector3& normal() const {
- return _normal;
- }
+ 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.
@@ -124,7 +132,7 @@ public:
return (_normal.dot(x) - _distance);
}
- inline Vector3 closestPoint(const Vector3& x) const {
+ inline Point3 closestPoint(const Point3& x) const {
return x + (_normal * (-distance(x)));
}
@@ -144,8 +152,8 @@ public:
<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;
+ void getEquation(Vector3& normal, double& d) const;
+ void getEquation(Vector3& normal, float& d) const;
/**
ax + by + cz + d = 0
diff --git a/dep/g3dlite/include/G3D/PointHashGrid.h b/dep/g3dlite/include/G3D/PointHashGrid.h
index d0b60a88ae5..85c50229642 100644
--- a/dep/g3dlite/include/G3D/PointHashGrid.h
+++ b/dep/g3dlite/include/G3D/PointHashGrid.h
@@ -1,11 +1,11 @@
/**
- @file PointHashGrid.h
+ \file PointHashGrid.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2008-07-01
- @edited 2009-05-28
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2008-07-01
+ \edited 2010-11-28
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_PointHashGrid_h
@@ -25,23 +25,23 @@
namespace G3D {
/**
- Storage of data in a sparse 3D grid of point-based data. The
- space cost for <I>n</I> elements is O(<I>n</I>). For data with
+ \brief A sparse 3D grid of point-based data.
+
+ The space cost for <I>n</I> elements is O(<I>n</I>). For data with
approximately uniform density (with respect to the radius hint),
the time cost of searching for neighbors is O(1).
- <i>Value</i> must be supported by a G3D::PositionTrait and
- G3D::EqualsTrait. Overloads are provided for
- common G3D classes like G3D::Vector3. For example:
-
- <pre>
- class EqualsFunc {
- public:
- static bool equals(const Data& p, const Data& q) {
- return p == q;
- }
- };
+ You can move members of the data set by first removing them and then
+ adding them with a new location.
+ Template argument \a PosFunc must provide a static <code>getPosition</code> method
+ and \a EqualsFunc must provide a static <code>equals</code> method, as described below.
+ You can either write classes that support these yourself, provide template specializations of
+ G3D::PositionTrait and
+ G3D::EqualsTrait, or rely on the default template specializations, which already exist for
+ common G3D classes like G3D::Point3. For example:
+
+ \code
class PosFunc {
public:
static void getPosition(const Data& d, Vector3& pos) {
@@ -49,14 +49,43 @@ namespace G3D {
}
};
+ class EqualsFunc {
+ public:
+ static bool equals(const Data& p, const Data& q) {
+ return p == q;
+ }
+ };
+
PointHashGrid<Data, Data::PosFunc, Data::EqualsFunc> grid;
- </pre>
+ \endcode
- If the Value class defines operator==, the Equalsfunc is optional:
+ If the \a Value class defines <code>operator==</code>, then the \a Equalsfunc is optional, so you can just write:
- <pre>
+ \code
PointHashGrid<Data, Data::PosFunc> grid;
- </pre>
+ \endcode
+
+ The simplest way to define these is often to make them both methods
+ of the parameter class itself, e.g.,
+
+ \code
+
+ class Data {
+ public:
+ Point3 location;
+ ...
+
+ bool operator==(const Data& other) const {
+ return (location == other.location) && ...;
+ }
+
+ static void getPosition(const Data& p, Vector3& pos) {
+ pos = p.location;
+ }
+ };
+
+ typedef PointHashGrid<Data, Data> DataGrid;
+ \endcode
*/
template<class Value,
@@ -65,20 +94,20 @@ template<class Value,
class PointHashGrid {
private:
-# define expectedCellSize (3)
+# define expectedCellSize (10)
# define ThisType PointHashGrid<Value, PosFunc, EqualsFunc>
/** A value annotated with precomputed position and hash code.*/
class Entry {
public:
- Vector3 position;
- Value value;
+ Point3 position;
+ Value value;
};
/** One cell of the grid. */
typedef SmallArray<Entry, expectedCellSize> Cell;
- typedef Table<Vector3int32, Cell > CellTable;
+ typedef Table<Point3int32, Cell > CellTable;
/** The cube of +/-1 along each dimension. Initialized by initOffsetArray.*/
Vector3int32 m_offsetArray[3*3*3];
@@ -116,18 +145,19 @@ private:
/** Locate the cell and index within that cell containing v. Called by
remove() and contains(). */
- bool find(const Value& v,
- Vector3int32& foundCellCoord,
- Cell*& foundCell,
- int& index) {
+ bool find
+ (const Value& v,
+ Point3int32& foundCellCoord,
+ Cell*& foundCell,
+ int& index) {
- Vector3 pos;
+ Point3 pos;
PosFunc::getPosition(v, pos);
- Vector3int32 cellCoord;
+ Point3int32 cellCoord;
getCellCoord(pos, cellCoord);
for (int i = 0; i < 27; ++i) {
- Vector3int32 c = cellCoord + m_offsetArray[i];
+ Point3int32 c = cellCoord + m_offsetArray[i];
Cell* cell = m_data.getPointer(c);
if (cell != NULL) {
// The cell exists
@@ -146,18 +176,25 @@ private:
return false;
}
- /** Given a real-space position, returns the cell coord
- containing it.*/
- inline void getCellCoord(const Vector3& pos, Vector3int32& cellCoord) const {
+public:
+
+ /** \brief Compute the grid cell index of a real position.
+ This is used extensively internally by PointHashGrid.
+ It is useful to calling code to determine when an object
+ is about to move between cells.
+ */
+ inline void getCellCoord(const Point3& pos, Point3int32& cellCoord) const {
for (int a = 0; a < 3; ++a) {
cellCoord[a] = iFloor(pos[a] * m_invCellWidth);
}
}
+protected:
+
/** Initializes m_offsetArray. */
void initOffsetArray() {
int i = 0;
- Vector3int32 d;
+ Point3int32 d;
for (d.x = -1; d.x <= +1; ++d.x) {
for (d.y = -1; d.y <= +1; ++d.y) {
for (d.z = -1; d.z <= +1; ++d.z) {
@@ -179,9 +216,10 @@ private:
public:
/**
- @param radiusHint the radius that will typically be used with
- beginSphereIntersection and beginBoxIntersection. If two <i>Value</i>s are equal,
- their positions must be within this radius as well.
+ \param radiusHint the radius that will typically be used with
+ beginBallIntersection and beginBoxIntersection. If two <i>Value</i>s are equal,
+ their positions must be within this radius as well. You can later change this
+ value with clearAndSetRadiusHint().
*/
PointHashGrid(float radiusHint, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
initOffsetArray();
@@ -192,23 +230,41 @@ public:
m_invCellWidth = 1.0f / m_cellWidth;
}
+ /** \sa clearAndSetRadiusHint() */
+ float radiusHint() const {
+ return m_cellWidth;
+ }
+
+ void clear(float radiusHint) {
+ debugAssertM(radiusHint > 0, "Cell radius must be positive");
+ clear();
+ m_cellWidth = radiusHint;
+ m_invCellWidth = 1.0f / m_cellWidth;
+ }
+
+ void clearAndSetRadiusHint(float radiusHint) {
+ return clear(radiusHint);
+ }
+
/**
- If radiusHint is negative, it is automatically chosen to put
+ If \a radiusHint is negative, it is automatically chosen to put
about 5 values in each grid cell (which means about 27 * 5
values for each beginIntersection call).
+
+ \sa clearAndSetRadiusHint()
*/
- PointHashGrid(const Array<Value>& init, float radiusHint = -1.0f, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
+ PointHashGrid(const Array<Value>& init, float radiusHint = -1.0f, const MemoryManager::Ref& m = MemoryManager::create()) : m_size(0), m_memoryManager(m) {
initOffsetArray();
m_data.clearAndSetMemoryManager(m_memoryManager);
- Vector3 lo(Vector3::inf());
- Vector3 hi(-lo);
+ Point3 lo(Vector3::inf());
+ Point3 hi(-lo);
// Compute bounds
Array<Entry> entry(init.size());
for (int i = 0; i < entry.size(); ++i) {
const Value& value = init[i];
- Vector3 pos;
+ Point3 pos;
entry[i].value = value;
entry[i].hashCode = m_hashFunc(value);
@@ -241,7 +297,7 @@ public:
}
/** Returns the number of elements. */
- inline int size() const {
+ int size() const {
return m_size;
}
@@ -251,13 +307,19 @@ public:
return m_bounds;
}
+ void debugPrintStatistics() const {
+ debugPrintf("Deepest bucket size = %d\n", (int)m_data.debugGetDeepestBucketSize());
+ debugPrintf("Average bucket size = %g\n", m_data.debugGetAverageBucketSize());
+ debugPrintf("Load factor = %g\n", m_data.debugGetLoad());
+ }
+
/** Insert @a v at position @a p given by <code>getPosition(v, p)</code>.
Multiple elements that are equal may be inserted; all copies will be
in the data structure. */
void insert(const Value& v) {
- Vector3 pos;
+ Point3 pos;
PosFunc::getPosition(v, pos);
- Vector3int32 cellCoord;
+ Point3int32 cellCoord;
getCellCoord(pos, cellCoord);
// See if the cell already exists
@@ -316,7 +378,8 @@ public:
// Drop our pointer, which is about to dangle
cell = NULL;
- bool success = m_data.remove(cellCoord);
+ const bool success = m_data.remove(cellCoord);
+ (void)success;
debugAssertM(success, "Data structure corrupt: "
"tried to remove a cell that doesn't exist.");
}
@@ -328,7 +391,7 @@ public:
}
}
- /** Removes all elements of @v. */
+ /** Removes all elements of \a v. */
void remove(const Array<Value>& v, bool shrink = true) {
for (int i = 0; i < v.size(); ++i) {
remove(v[i], shrink);
@@ -387,6 +450,11 @@ public:
}
}
+ bool isValid() const {
+ return ! m_isEnd;
+ }
+
+ /** @deprecated Use isValid */
bool hasMore() const {
return ! m_isEnd;
}
@@ -615,9 +683,14 @@ public:
const Value* operator->() const { return &value(); }
operator Value*() const { return &value(); }
+ /** \deprecated Use isValid */
bool hasMore() const {
return ! m_isEnd;
}
+
+ bool isValid() const {
+ return ! m_isEnd;
+ }
}; // BoxIterator
/**
@@ -652,7 +725,7 @@ public:
SphereIterator() : m_isEnd(true) {}
void advance() {
- if (! m_boxIterator.hasMore()) {
+ if (! m_boxIterator.isValid()) {
m_isEnd = true;
return;
}
@@ -660,7 +733,7 @@ public:
while (! m_sphere.contains(m_boxIterator.position())) {
++m_boxIterator;
- if (! m_boxIterator.hasMore()) {
+ if (! m_boxIterator.isValid()) {
m_isEnd = true;
return;
}
@@ -677,13 +750,13 @@ public:
m_isEnd(false),
m_sphere(sphere),
m_boxIterator(grid, false, getBoundingBox(sphere)) {
-
+
// Find the first element that is actually in the sphere,
// not just the box.
advance();
}
- const Value& value() const {
+ const Value& value() const {
return *m_boxIterator;
}
@@ -693,6 +766,7 @@ public:
// Intentionally unimplemented
SphereIterator& operator=(const SphereIterator&);
+
public:
inline bool operator!=(const SphereIterator& other) const {
@@ -710,8 +784,6 @@ public:
return !(*this != other);
}
-
-
/** Preincrement */
SphereIterator& operator++() {
debugAssert(! m_isEnd);
@@ -733,34 +805,55 @@ public:
const Value* operator->() const { return &value(); }
operator Value*() const { return &value(); }
- bool hasMore() const {
+ /** \deprecated use isValid */
+ bool G3D_DEPRECATED hasMore() const {
+ return ! m_isEnd;
+ }
+
+ bool isValid() const {
return ! m_isEnd;
}
}; // SphereIterator
- /**
- Finds all values whose positions are within @a sphere. It is an error
- to mutate the HashGrid while iterating through it.
- */
- SphereIterator beginSphereIntersection(const Sphere& sphere) const {
+ /** Finds all values whose positions are within \a sphere. It is
+ an error to mutate the PointHashGrid while iterating through
+ it. */
+ SphereIterator begin(const Sphere& sphere) const {
return SphereIterator(this, sphere);
}
+
+ /** \deprecated \sa beginIntersection */
+ SphereIterator G3D_DEPRECATED beginSphereIntersection(const Sphere& sphere) const {
+ return SphereIterator(this, sphere);
+ }
+
+
+ /** \deprecated \sa SphereIterator::hasMore */
const SphereIterator& endSphereIntersection() const {
static const SphereIterator it;
return it;
}
+
+ /** Appends results */
+ void getIntersectingMembers(const Sphere& sphere, Array<Value>& result) const {
+ for (SphereIterator it = beginSphereIntersection(sphere); it.isValid(); ++it) {
+ result.append(*it);
+ }
+ }
+
+
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////
/**
Dereference to access the bounds() and size() [element count] of the underlying
- cell objet.
+ cell object.
Example:
<pre>
- for(PointHashGrid<Vector3>::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {
+ for(PointHashGrid<Vector3>::CellIterator iter = grid.beginCells(); iter != grid.endCells(); ++iter) {
entriesFound += iter->size();
}
</pre>
@@ -793,8 +886,8 @@ public:
/** Returns the bounds on this cell */
AABox bounds() const {
const Vector3int32& k = m_parent->m_tableIterator->key;
- return AABox(Vector3(k) * m_parent->m_cellWidth,
- Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_cellWidth);
+ return AABox(Vector3(k) * m_parent->m_grid->m_cellWidth,
+ Vector3(k + Vector3int32(1, 1, 1)) * m_parent->m_grid->m_cellWidth);
}
/** Number of elements inside this cell */
@@ -823,7 +916,7 @@ public:
m_tableIterator( grid->m_data.begin()),
m_epoch(grid->m_epoch) {
m_indirection.m_parent = this;
- m_isEnd = ! m_tableIterator.hasMore();
+ m_isEnd = ! m_tableIterator.isValid();
}
// Intentionally unimplemented
@@ -853,7 +946,7 @@ public:
"It is illegal to mutate the HashGrid while "
"iterating through it.");
++m_tableIterator;
- m_isEnd = ! m_tableIterator.hasMore();
+ m_isEnd = ! m_tableIterator.isValid();
return *this;
}
@@ -864,9 +957,14 @@ public:
return old;
}
+ /** \deprecated Use isValid */
bool hasMore() const {
return ! m_isEnd;
}
+
+ bool isValid() const {
+ return ! m_isEnd;
+ }
}; // CellIterator
/** Iterates through the non-empty cells. This is intended primarily for
@@ -897,11 +995,11 @@ public:
This is a helper to avoid requiring you to iterate through the data
structure, removing and deleting each one. Clears the PointHashGrid at the
end.
-
+
Using objects (instead of pointers) or reference counted pointers is
recommended over using pointers and this deleteAll method.*/
void deleteAll() {
- for (Iterator it = begin(); it.hasMore(); ++it) {
+ for (Iterator it = begin(); it.isValid(); ++it) {
delete *it;
}
clear();
@@ -924,7 +1022,7 @@ public:
m_bounds = AABox();
if (! shrink) {
// Remove all data
- for (CellIterator it = beginCells(); it.hasMore(); ++it) {
+ for (CellIterator it = beginCells(); it.isValid(); ++it) {
it.cell().clear(true);
}
} else {
@@ -934,7 +1032,7 @@ public:
}
int debugGetDeepestBucketSize() const {
- return m_data.debugGetDeepestBucketSize();
+ return (int)m_data.debugGetDeepestBucketSize();
}
float debugGetAverageBucketSize() const {
diff --git a/dep/g3dlite/include/G3D/PointKDTree.h b/dep/g3dlite/include/G3D/PointKDTree.h
index 151cbd5f2f3..8ea7cf8d077 100644
--- a/dep/g3dlite/include/G3D/PointKDTree.h
+++ b/dep/g3dlite/include/G3D/PointKDTree.h
@@ -4,15 +4,15 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2004-01-11
- @edited 2008-11-02
+ @edited 2012-07-30
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef X_PointKDTree_H
-#define X_PointKDTree_H
+#ifndef G3D_PointKDTree_h
+#define G3D_PointKDTree_h
#include "G3D/platform.h"
#include "G3D/Array.h"
@@ -26,7 +26,7 @@
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/CollisionDetection.h"
-#include "G3D/GCamera.h"
+#include "G3D/Frustum.h"
#include "G3D/PositionTrait.h"
#include <algorithm>
@@ -234,36 +234,38 @@ protected:
}
- void verifyNode(const Vector3& lo, const Vector3& hi) {
- // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
- // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
+ void verifyNode(const Vector3& lo, const Vector3& hi) {
+ // debugPrintf("Verifying: split %d @ %f [%f, %f, %f], [%f, %f, %f]\n",
+ // splitAxis, splitLocation, lo.x, lo.y, lo.z, hi.x, hi.y, hi.z);
debugAssert(lo == splitBounds.low());
debugAssert(hi == splitBounds.high());
- for (int i = 0; i < valueArray.length(); ++i) {
- const Vector3& b = valueArray[i].position();
+# ifdef G3D_DEBUG
+ for (int i = 0; i < valueArray.length(); ++i) {
+ const Vector3& b = valueArray[i].position();
debugAssert(splitBounds.contains(b));
- }
+ }
+# endif
- if (child[0] || child[1]) {
- debugAssert(lo[splitAxis] < splitLocation);
- debugAssert(hi[splitAxis] > splitLocation);
- }
+ if (child[0] || child[1]) {
+ debugAssert(lo[splitAxis] < splitLocation);
+ debugAssert(hi[splitAxis] > splitLocation);
+ }
- Vector3 newLo = lo;
- newLo[splitAxis] = splitLocation;
- Vector3 newHi = hi;
- newHi[splitAxis] = splitLocation;
+ Vector3 newLo = lo;
+ newLo[splitAxis] = splitLocation;
+ Vector3 newHi = hi;
+ newHi[splitAxis] = splitLocation;
- if (child[0] != NULL) {
- child[0]->verifyNode(lo, newHi);
- }
+ if (child[0] != NULL) {
+ child[0]->verifyNode(lo, newHi);
+ }
- if (child[1] != NULL) {
- child[1]->verifyNode(newLo, hi);
- }
- }
+ if (child[1] != NULL) {
+ child[1]->verifyNode(newLo, hi);
+ }
+ }
/**
@@ -297,6 +299,7 @@ protected:
for (int c = 0; c < 2; ++c) {
n->child[c] = deserializeStructure(bi);
}
+ return n;
}
}
@@ -484,7 +487,7 @@ protected:
// Compute the mean along the axis
splitLocation = (bounds.high()[splitAxis] +
- bounds.low()[splitAxis]) / 2.0;
+ bounds.low()[splitAxis]) / 2.0f;
Handle splitHandle;
Vector3 v;
@@ -525,10 +528,10 @@ protected:
for(int i = 0; i < node->valueArray.size(); ++i) {
memberTable.set(node->valueArray[i].value, node);
}
-
- }
-
- return node;
+
+ }
+
+ return node;
}
/**
@@ -611,7 +614,7 @@ public:
}
- int size() const {
+ size_t size() const {
return memberTable.size();
}
@@ -809,7 +812,7 @@ private:
// Test values at this node against remaining planes
for (int p = 0; p < plane.size(); ++p) {
- if ((parentMask >> p) & 1 != 0) {
+ if (((parentMask >> p) & 1) != 0) {
// Test against this plane
const Plane& curPlane = plane[p];
for (int v = node->valueArray.size() - 1; v >= 0; --v) {
@@ -851,7 +854,7 @@ public:
/**
Typically used to find all visible
- objects inside the view frustum (see also GCamera::getClipPlanes)... i.e. all objects
+ objects inside the view frustum (see also Camera::getClipPlanes)... i.e. all objects
<B>not</B> culled by frustum.
Example:
@@ -862,7 +865,7 @@ public:
</PRE>
@param members The results are appended to this array.
*/
- void getIntersectingMembers(const GCamera::Frustum& frustum, Array<T>& members) const {
+ void getIntersectingMembers(const Frustum& frustum, Array<T>& members) const {
Array<Plane> plane;
for (int i = 0; i < frustum.faceArray.size(); ++i) {
@@ -960,51 +963,51 @@ public:
BoxIntersectionIterator& operator++() {
++nextValueArrayIndex;
- bool foundIntersection = false;
+ bool foundIntersection = false;
while (! isEnd && ! foundIntersection) {
- // Search for the next node if we've exhausted this one
+ // Search for the next node if we've exhausted this one
while ((! isEnd) && (nextValueArrayIndex >= node->valueArray.length())) {
- // If we entered this loop, then the iterator has exhausted the elements at
- // node (possibly because it just switched to a child node with no members).
- // This loop continues until it finds a node with members or reaches
- // the end of the whole intersection search.
-
- // If the right child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[1] != NULL) &&
- (box.high()[node->splitAxis] > node->splitLocation)) {
- stack.push(node->child[1]);
- }
+ // If we entered this loop, then the iterator has exhausted the elements at
+ // node (possibly because it just switched to a child node with no members).
+ // This loop continues until it finds a node with members or reaches
+ // the end of the whole intersection search.
+
+ // If the right child overlaps the box, push it onto the stack for
+ // processing.
+ if ((node->child[1] != NULL) &&
+ (box.high()[node->splitAxis] > node->splitLocation)) {
+ stack.push(node->child[1]);
+ }
- // If the left child overlaps the box, push it onto the stack for
- // processing.
- if ((node->child[0] != NULL) &&
- (box.low()[node->splitAxis] < node->splitLocation)) {
- stack.push(node->child[0]);
- }
-
- if (stack.length() > 0) {
- // Go on to the next node (which may be either one of the ones we
- // just pushed, or one from farther back the tree).
- node = stack.pop();
- nextValueArrayIndex = 0;
- } else {
- // That was the last node; we're done iterating
- isEnd = true;
- }
- }
-
- // Search for the next intersection at this node until we run out of children
- while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
- if (box.intersects(node->valueArray[nextValueArrayIndex].bounds)) {
- foundIntersection = true;
- } else {
- ++nextValueArrayIndex;
- // If we exhaust this node, we'll loop around the master loop
- // to find a new node.
- }
- }
+ // If the left child overlaps the box, push it onto the stack for
+ // processing.
+ if ((node->child[0] != NULL) &&
+ (box.low()[node->splitAxis] < node->splitLocation)) {
+ stack.push(node->child[0]);
+ }
+
+ if (stack.length() > 0) {
+ // Go on to the next node (which may be either one of the ones we
+ // just pushed, or one from farther back the tree).
+ node = stack.pop();
+ nextValueArrayIndex = 0;
+ } else {
+ // That was the last node; we're done iterating
+ isEnd = true;
+ }
+ }
+
+ // Search for the next intersection at this node until we run out of children
+ while (! isEnd && ! foundIntersection && (nextValueArrayIndex < node->valueArray.length())) {
+ if (box.intersects(node->valueArray[nextValueArrayIndex].bounds)) {
+ foundIntersection = true;
+ } else {
+ ++nextValueArrayIndex;
+ // If we exhaust this node, we'll loop around the master loop
+ // to find a new node.
+ }
+ }
}
return *this;
diff --git a/dep/g3dlite/include/G3D/Pointer.h b/dep/g3dlite/include/G3D/Pointer.h
index 6e35062a746..61894fba097 100644
--- a/dep/g3dlite/include/G3D/Pointer.h
+++ b/dep/g3dlite/include/G3D/Pointer.h
@@ -1,12 +1,12 @@
/**
- @file Pointer.h
+ \file Pointer.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-05-16
- @edited 2009-03-26
+ \created 2007-05-16
+ \edited 2012-10-06
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_Pointer_h
@@ -27,7 +27,7 @@ namespace G3D {
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.
- <pre>
+ \code
class Foo {
public:
void setEnabled(bool b);
@@ -51,14 +51,15 @@ namespace G3D {
p2.setValue(p1.getValue());
p2 = p1;
- </pre>
+ \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<class ValueType>
+template<typename ValueType>
class Pointer {
private:
@@ -78,9 +79,7 @@ private:
public:
- Memory(ValueType* value) : value(value) {
- //debugAssert(value != NULL);
- }
+ Memory(ValueType* value) : value(value) {}
virtual void set(ValueType v) {
*value = v;
@@ -99,6 +98,35 @@ private:
}
};
+ 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:
@@ -116,7 +144,9 @@ private:
}
virtual void set(ValueType v) {
- (object->*setMethod)(v);
+ if (setMethod) {
+ (object->*setMethod)(v);
+ }
}
virtual ValueType get() const {
@@ -134,17 +164,17 @@ private:
template<class T, typename GetMethod, typename SetMethod>
- class RefAccessor : public Interface {
+ class SharedAccessor : public Interface {
private:
- ReferenceCountedPointer<T> object;
- GetMethod getMethod;
- SetMethod setMethod;
+ shared_ptr<T> object;
+ GetMethod getMethod;
+ SetMethod setMethod;
public:
- RefAccessor(
- const ReferenceCountedPointer<T>& object,
+ SharedAccessor
+ (const shared_ptr<T>& object,
GetMethod getMethod,
SetMethod setMethod) : object(object), getMethod(getMethod), setMethod(setMethod) {
@@ -152,23 +182,24 @@ private:
}
virtual void set(ValueType v) {
- (object.pointer()->*setMethod)(v);
+ if (setMethod) {
+ (object.get()->*setMethod)(v);
+ }
}
virtual ValueType get() const {
- return (object.pointer()->*getMethod)();
+ return (object.get()->*getMethod)();
}
virtual Interface* clone() const {
- return new RefAccessor(object, getMethod, setMethod);
+ return new SharedAccessor(object, getMethod, setMethod);
}
virtual bool isNull() const {
- return object.isNull();
+ return (bool)object;
}
};
-
Interface* m_interface;
public:
@@ -197,48 +228,69 @@ public:
this[0] = p;
}
+
+ /** \param setMethod May be NULL */
template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
+ Pointer(const shared_ptr<Class>& object,
ValueType (Class::*getMethod)() const,
void (Class::*setMethod)(ValueType)) :
- m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
+ m_interface(new SharedAccessor<Class, ValueType (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
+ /** \param setMethod May be NULL */
template<class Class>
- Pointer(const ReferenceCountedPointer<Class>& object,
+ Pointer(const shared_ptr<Class>& object,
const ValueType& (Class::*getMethod)() const,
void (Class::*setMethod)(ValueType)) :
- m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(ValueType)>(object, getMethod, setMethod)) {}
+ 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 ReferenceCountedPointer<Class>& object,
+ Pointer(const shared_ptr<Class>& object,
ValueType (Class::*getMethod)() const,
void (Class::*setMethod)(const ValueType&)) :
- m_interface(new RefAccessor<Class, ValueType (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
+ 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 ReferenceCountedPointer<Class>& object,
+ Pointer(const shared_ptr<Class>& object,
const ValueType& (Class::*getMethod)() const,
void (Class::*setMethod)(const ValueType&)) :
- m_interface(new RefAccessor<Class, const ValueType& (Class::*)() const, void (Class::*)(const ValueType&)>(object, getMethod, setMethod)) {}
+ 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,
@@ -254,6 +306,8 @@ public:
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);
@@ -287,6 +341,16 @@ public:
}
};
+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
diff --git a/dep/g3dlite/include/G3D/Quat.h b/dep/g3dlite/include/G3D/Quat.h
index d8fdfafeca4..04e11e084a0 100644
--- a/dep/g3dlite/include/G3D/Quat.h
+++ b/dep/g3dlite/include/G3D/Quat.h
@@ -1,12 +1,12 @@
/**
- @file Quat.h
+ \file G3D/Quat.h
Quaternion
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-01-23
- @edited 2009-05-10
+ \created 2002-01-23
+ \edited 2011-05-10
*/
#ifndef G3D_Quat_h
@@ -21,9 +21,9 @@
namespace G3D {
/**
- Arbitrary quaternion (not necessarily unit)
+ Arbitrary quaternion (not necessarily unit).
- Unit quaternions are used in computer graphics to represent
+ 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.
@@ -72,6 +72,8 @@ public:
/** 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) :
@@ -81,6 +83,12 @@ public:
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.
*/
@@ -92,9 +100,9 @@ public:
return w;
}
- Quat operator-() const {
- return Quat(-x, -y, -z, -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);
@@ -148,7 +156,7 @@ public:
}
- /** @cite Based on Watt & Watt, page 360 */
+ /** @cite Based on Watt & Watt, page 360 */
friend Quat operator* (float s, const Quat& q);
inline Quat operator/(float s) const {
@@ -196,36 +204,69 @@ public:
void toAxisAngleRotation(
Vector3& axis,
float& angle) const {
- double d;
- toAxisAngleRotation(axis, d);
- angle = (float)d;
- }
+ 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 at which
- the algorithm switches to normalized lerp, which is more
- numerically stable in those situations. 0.0 will always slerp.
+ \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,
+ Quat slerp
+ (const Quat& other,
float alpha,
- float threshold = 0.05f) const;
+ float threshold = 0.05f) const {
+ return slerp(other, alpha, threshold, finf());
+ }
- /** Normalized linear interpolation of quaternion components. */
- Quat nlerp(const Quat& other, float alpha) const;
+ /** 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 */
@@ -274,22 +315,6 @@ public:
return Quat(t * x, t * y, t * z, ::logf(len));
}
}
- /** log q = [Av, 0] where q = [sin(A) * v, cos(A)].
- Only for unit quaternions
- debugAssertM(isUnit(), "Log only defined for unit quaternions");
- // Solve for A in q = [sin(A)*v, cos(A)]
- Vector3 u(x, y, z);
- double len = u.magnitude();
-
- if (len == 0.0) {
- return
- }
- double A = atan2((double)w, len);
- Vector3 v = u / len;
-
- return Quat(v * A, 0);
- }
- */
/** exp q = [sin(A) * v, cos(A)] where q = [Av, 0].
Only defined for pure-vector quaternions */
@@ -348,7 +373,7 @@ public:
float& operator[] (int i);
/** Generate uniform random unit quaternion (i.e. random "direction")
- @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
+ @cite From "Uniform Random Rotations", Ken Shoemake, Graphics Gems III.
*/
static Quat unitRandom();
diff --git a/dep/g3dlite/include/G3D/Queue.h b/dep/g3dlite/include/G3D/Queue.h
index 36573265d1a..c560eb426e0 100644
--- a/dep/g3dlite/include/G3D/Queue.h
+++ b/dep/g3dlite/include/G3D/Queue.h
@@ -7,8 +7,8 @@
@edited 2008-12-20
*/
-#ifndef G3D_QUEUE_H
-#define G3D_QUEUE_H
+#ifndef G3D_Queue_h
+#define G3D_Queue_h
#include "G3D/platform.h"
#include "G3D/System.h"
@@ -23,6 +23,8 @@ namespace G3D {
sequence without using the modulo operator.
[0 ... secondEnd) [head .... firstEnd)
+
+ \sa ThreadsafeQueue
*/
#define FIND_ENDS \
int firstEnd = head + num;\
@@ -325,6 +327,10 @@ public:
return (*this)[size() - 1];
}
+ bool empty() const {
+ return size() == 0;
+ }
+
/**
Returns true if the given element is in the queue.
*/
@@ -346,7 +352,7 @@ public:
FIND_ENDS;
int i;
- for (i = 0; i < secondEnd; ++i) {
+ for (i = 0; i < secondEnd; ++i) {
delete data[i];
}
diff --git a/dep/g3dlite/include/G3D/Random.h b/dep/g3dlite/include/G3D/Random.h
index 54491d06f1b..9d911806a97 100644
--- a/dep/g3dlite/include/G3D/Random.h
+++ b/dep/g3dlite/include/G3D/Random.h
@@ -1,12 +1,12 @@
/**
- @file Random.h
+ \file G3D/Random.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-01-02
- @edited 2009-03-20
+ \created 2009-01-02
+ \edited 2012-07-20
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#ifndef G3D_Random_h
@@ -33,6 +33,8 @@ namespace G3D {
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:
@@ -71,6 +73,23 @@ protected:
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
@@ -81,6 +100,8 @@ public:
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();
@@ -109,9 +130,13 @@ public:
virtual float gaussian(float mean, float stdev);
/** Returns 3D unit vectors distributed according to
- a cosine distribution about the z-axis. */
+ 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. */
diff --git a/dep/g3dlite/include/G3D/Ray.h b/dep/g3dlite/include/G3D/Ray.h
index 80df5828aff..1ca77c242d2 100644
--- a/dep/g3dlite/include/G3D/Ray.h
+++ b/dep/g3dlite/include/G3D/Ray.h
@@ -25,78 +25,85 @@ class Ray {
private:
friend class Intersect;
- Vector3 m_origin;
+ Point3 m_origin;
- /** Unit length */
- Vector3 m_direction;
+ /** Unit length */
+ Vector3 m_direction;
- /** 1.0 / direction */
- Vector3 m_invDirection;
+ /** 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ü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};
- // 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ü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:
-
- void set(const Vector3& origin, const Vector3& direction);
-
- inline const Vector3& origin() const {
- return m_origin;
- }
+ Classification classification;
- /** Unit direction vector. */
- inline const Vector3& direction() const {
- return m_direction;
- }
+ /** ray slope */
+ float ibyj, jbyi, kbyj, jbyk, ibyk, kbyi;
- /** Component-wise inverse of direction vector. May have inf() components */
- inline const Vector3& invDirection() const {
- return m_invDirection;
- }
+ /** Precomputed components */
+ float c_xy, c_xz, c_yx, c_yz, c_zx, c_zy;
- inline Ray() {
- set(Vector3::zero(), Vector3::unitX());
- }
+public:
+ /** \param direction Assumed to have unit length */
+ void set(const Point3& origin, const Vector3& direction);
- inline Ray(const Vector3& origin, const Vector3& direction) {
- set(origin, direction);
- }
+ const Point3& origin() const {
+ return m_origin;
+ }
+
+ /** Unit direction vector. */
+ const Vector3& direction() const {
+ return m_direction;
+ }
- Ray(class BinaryInput& b);
+ /** Component-wise inverse of direction vector. May have inf() components */
+ const Vector3& invDirection() const {
+ return m_invDirection;
+ }
+
+ Ray() {
+ set(Point3::zero(), Vector3::unitX());
+ }
- void serialize(class BinaryOutput& b) const;
- void deserialize(class BinaryInput& b);
+ /** \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 Vector3& point, const Vector3& direction) {
+ 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);
+ }
- /** Advances the origin along the direction by @a distance */
- inline Ray bump(float distance) const {
- return Ray(m_origin + m_direction * distance, m_direction);
- }
-
- /** Advances the origin along the @a bumpDirection by @a distance and returns the new ray*/
- inline Ray bump(float distance, const Vector3& bumpDirection) const {
- return Ray(m_origin + bumpDirection * 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);
+ }
/**
- Returns the closest point on the Ray to point.
- */
- Vector3 closestPoint(const Vector3& point) const {
+ \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;
@@ -108,7 +115,7 @@ public:
/**
Returns the closest distance between point and the Ray
*/
- float distance(const Vector3& point) const {
+ float distance(const Point3& point) const {
return (closestPoint(point) - point).magnitude();
}
@@ -119,7 +126,7 @@ public:
Planes are considered one-sided, so the ray will not intersect
a plane where the normal faces in the traveling direction.
*/
- Vector3 intersection(const class Plane& plane) const;
+ Point3 intersection(const class Plane& plane) const;
/**
Returns the distance until intersection with the sphere or the (solid) ball bounded by the sphere.
@@ -151,54 +158,56 @@ public:
float intersectionTime(
const Vector3& v0, const Vector3& v1, const Vector3& v2,
const Vector3& edge01, const Vector3& edge02,
- double& w0, double& w1, double& w2) const;
+ 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
*/
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
+ float intersectionTime(
+ const Point3& vert0,
+ const Point3& vert1,
+ const Point3& vert2,
const Vector3& edge01,
const Vector3& edge02) const;
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2) const {
+ float intersectionTime(
+ const Point3& vert0,
+ const Point3& vert1,
+ const Point3& vert2) const {
return intersectionTime(vert0, vert1, vert2, vert1 - vert0, vert2 - vert0);
}
- inline float intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- double& w0,
- double& w1,
- double& w2) const {
+ 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
*/
- inline float intersectionTime(const Triangle& triangle) const {
+ float intersectionTime(const Triangle& triangle) const {
return intersectionTime(
triangle.vertex(0), triangle.vertex(1), triangle.vertex(2),
triangle.edge01(), triangle.edge02());
}
- inline float intersectionTime(
- const Triangle& triangle,
- double& w0,
- double& w1,
- double& w2) const {
+
+ 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);
}
@@ -236,9 +245,9 @@ public:
dest[2]=v1[2]-v2[2];
inline float Ray::intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
+ const Point3& vert0,
+ const Point3& vert1,
+ const Point3& vert2,
const Vector3& edge1,
const Vector3& edge2) const {
@@ -294,15 +303,15 @@ inline float Ray::intersectionTime(
}
-inline float Ray::intersectionTime(
- const Vector3& vert0,
- const Vector3& vert1,
- const Vector3& vert2,
- const Vector3& edge1,
- const Vector3& edge2,
- double& w0,
- double& w1,
- double& w2) const {
+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;
diff --git a/dep/g3dlite/include/G3D/Rect2D.h b/dep/g3dlite/include/G3D/Rect2D.h
index 2fb58c50465..f72dd082ad8 100644
--- a/dep/g3dlite/include/G3D/Rect2D.h
+++ b/dep/g3dlite/include/G3D/Rect2D.h
@@ -1,12 +1,12 @@
/**
- @file Rect2D.h
+ \file Rect2D.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-11-13
- @created 2009-11-16
+ \created 2003-11-13
+ \created 2011-06-16
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -39,7 +39,7 @@ class Any;
*/
class Rect2D {
private:
- Vector2 min, max;
+ Point2 min, max;
/**
Returns true if the whole polygon is clipped.
@@ -117,38 +117,60 @@ private:
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. */
- operator Any() const;
+ Any toAny() const;
- Rect2D() : min(0, 0), max(0, 0) {}
+ 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) {}
- /** 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) {
- min = a.min.min(b.min);
- max = a.max.max(b.max);
+ Vector2 extent() const {
+ if (isEmpty()) {
+ return Vector2::zero();
+ } else {
+ return max - min;
+ }
}
/** @brief Uniformly random point on the interior */
- Vector2 randomPoint() const {
- return Vector2(uniformRandom(0, max.x - min.x) + min.x,
+ Point2 randomPoint() const {
+ return Point2(uniformRandom(0, max.x - min.x) + min.x,
uniformRandom(0, max.y - min.y) + min.y);
}
float width() const {
- return max.x - min.x;
+ if (isEmpty()) {
+ return 0;
+ } else {
+ return max.x - min.x;
+ }
}
float height() const {
- return max.y - min.y;
+ if (isEmpty()) {
+ return 0;
+ } else {
+ return max.y - min.y;
+ }
}
float x0() const {
@@ -168,29 +190,33 @@ public:
}
/** Min, min corner */
- Vector2 x0y0() const {
+ Point2 x0y0() const {
return min;
}
- Vector2 x1y0() const {
- return Vector2(max.x, min.y);
+ Point2 x1y0() const {
+ return Point2(max.x, min.y);
}
- Vector2 x0y1() const {
- return Vector2(min.x, max.y);
+ Point2 x0y1() const {
+ return Point2(min.x, max.y);
}
/** Max,max corner */
- Vector2 x1y1() const {
+ Point2 x1y1() const {
return max;
}
/** Width and height */
Vector2 wh() const {
- return max - min;
+ if (isEmpty()) {
+ return Vector2::zero();
+ } else {
+ return max - min;
+ }
}
- Vector2 center() const {
+ Point2 center() const {
return (max + min) * 0.5;
}
@@ -203,7 +229,7 @@ public:
}
Rect2D lerp(const Rect2D& other, float alpha) const {
- Rect2D out;
+ Rect2D out(false);
out.min = min.lerp(other.min, alpha);
out.max = max.lerp(other.max, alpha);
@@ -212,7 +238,7 @@ public:
}
static Rect2D xyxy(float x0, float y0, float x1, float y1) {
- Rect2D r;
+ Rect2D r(false);
r.min.x = G3D::min(x0, x1);
r.min.y = G3D::min(y0, y1);
@@ -222,8 +248,8 @@ public:
return r;
}
- static Rect2D xyxy(const Vector2& v0, const Vector2& v1) {
- Rect2D r;
+ static Rect2D xyxy(const Point2& v0, const Point2& v1) {
+ Rect2D r(false);
r.min = v0.min(v1);
r.max = v0.max(v1);
@@ -235,7 +261,7 @@ public:
return xyxy(x, y, x + w, y + h);
}
- static Rect2D xywh(const Vector2& v, const Vector2& w) {
+ static Rect2D xywh(const Point2& v, const Vector2& w) {
return xyxy(v.x, v.y, v.x + w.x, v.y + w.y);
}
@@ -246,11 +272,13 @@ public:
return xyxy(Vector2::inf(), Vector2::inf());
}
- bool contains(const Vector2& v) const {
+ 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);
}
@@ -259,12 +287,14 @@ public:
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);
}
@@ -273,6 +303,10 @@ public:
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);
}
@@ -297,21 +331,25 @@ public:
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). */
- Vector2 corner(int i) const {
+ Point2 corner(int i) const {
debugAssert(i >= 0 && i < 4);
switch (i & 3) {
case 0:
- return Vector2(min.x, min.y);
+ return Point2(min.x, min.y);
case 1:
- return Vector2(max.x, min.y);
+ return Point2(max.x, min.y);
case 2:
- return Vector2(max.x, max.y);
+ return Point2(max.x, max.y);
case 3:
- return Vector2(min.x, max.y);
+ return Point2(min.x, max.y);
default:
// Should never get here
- return Vector2(0, 0);
+ return Point2(0, 0);
}
}
@@ -345,6 +383,22 @@ public:
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.
@@ -398,15 +452,16 @@ public:
}
/**
- Returns the overlap region between the two rectangles. This may have zero area
- if they do not intersect. See the two-Rect2D constructor for a way to compute
- a union-like rectangle.
+ 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 Rect2D::xywh(0, 0, 0, 0);
+ } else {
+ return empty();
}
}
};
diff --git a/dep/g3dlite/include/G3D/ReferenceCount.h b/dep/g3dlite/include/G3D/ReferenceCount.h
index 84591c6d8e5..d3ac0391585 100644
--- a/dep/g3dlite/include/G3D/ReferenceCount.h
+++ b/dep/g3dlite/include/G3D/ReferenceCount.h
@@ -1,14 +1,12 @@
/**
- @file ReferenceCount.h
+ \file G3D/ReferenceCount.h
Reference Counting Garbage Collector for C++
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
- @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-10-23
- @edited 2009-04-25
+ \created 2001-10-23
+ \edited 2013-01-05
*/
#ifndef G3D_ReferenceCount_h
#define G3D_ReferenceCount_h
@@ -17,552 +15,40 @@
#include "G3D/debug.h"
#include "G3D/AtomicInt32.h"
-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
-
-/** Base class for WeakReferenceCountedPointer */
-class _WeakPtr {
-public:
- inline virtual ~_WeakPtr() {}
-
-protected:
- friend class ReferenceCountedObject;
-
- /** Called by ReferenceCountedObject to tell a weak pointer that its underlying object was collected. */
- virtual void objectCollected() = 0;
-};
-
-/** Used internally by ReferenceCountedObject */
-class _WeakPtrLinkedList {
-public:
- _WeakPtr* weakPtr;
- _WeakPtrLinkedList* next;
-
- inline _WeakPtrLinkedList() : weakPtr(NULL), next(NULL) {}
-
- /** Inserts this node into the head of the list that previously had n as its head. */
- inline _WeakPtrLinkedList(_WeakPtr* p, _WeakPtrLinkedList* n) : weakPtr(p), next(n) {}
-};
-
-/**
- Objects that are reference counted inherit from this. Subclasses
- <B>must</B> have a public destructor (the default destructor is fine)
- and <B>publicly</B> inherit ReferenceCountedObject.
-
- Multiple inheritance from a reference counted object is dangerous-- use
- at your own risk.
+#define USE_SHARED_PTR
- ReferenceCountedPointer and ReferenceCountedObject are threadsafe.
- You can create and drop references on multiple threads without
- violating integrity. WeakReferenceCountedPointer is <i>not</i>
- threadsafe. Introducing a weak pointer destroys all thread safety,
- even for strong pointers to the same object (this is inherent in the
- design of the class; we cannot fix it without slowing down the
- performance of reference counted objects.)
-
- <B>Usage Example</B>
-
- <PRE>
+#define ReferenceCountedPointer shared_ptr
+#define WeakReferenceCountedPointer weak_ptr
+namespace G3D {
-class Foo : public G3D::ReferenceCountedObject {
+class ReferenceCountedObject : public enable_shared_from_this<ReferenceCountedObject> {
public:
- int x;
+ virtual ~ReferenceCountedObject() {};
};
-class Bar : public Foo {};
-
-typedef G3D::ReferenceCountedPointer<Foo> FooRef;
-typedef G3D::WeakReferenceCountedPointer<Foo> WeakFooRef;
-typedef G3D::ReferenceCountedPointer<Bar> BarRef;
-
-
-int main(int argc, char *argv[]) {
-
- WeakFooRef x;
-
- {
- FooRef a = new Foo();
-
- // Reference count == 1
-
- x = a;
- // Weak references do not increase count
-
- {
- FooRef b = a;
- // Reference count == 2
- }
-
- // Reference count == 1
- }
- // No more strong references; object automatically deleted.
- // x is set to NULL automatically.
-
- // Example of using dynamic cast on reference counted objects
- BarRef b = new Bar();
-
- // No cast needed to go down the heirarchy.
- FooRef f = b;
+} // namespace
- // We can't cast the reference object because it is a class.
- // Instead we must extract the pointer and cast that:
- b = dynamic_cast<Bar*>(&*f);
+namespace G3D {
- return 0;
+template<class T>
+bool isNull(const ReferenceCountedPointer<T>& ptr) {
+ return ! ptr;
}
-</PRE>
- */
-class ReferenceCountedObject {
-public:
-
- /**
- The long name is to keep this from accidentally conflicting with
- a subclass's variable name. Do not use or explicitly manipulate
- this value--its type may change in the future and is not part
- of the supported API.
- */
- AtomicInt32 ReferenceCountedObject_refCount;
-
- /**
- Linked list of all weak pointers that reference this (some may be
- on the stack!). Do not use or explicitly manipulate this value.
- */
- _WeakPtrLinkedList* ReferenceCountedObject_weakPointer;
-
-protected:
-
- ReferenceCountedObject();
-
-public:
-
- /** Automatically called immediately before the object is deleted.
- This is not called from the destructor because it needs to be invoked
- before the subclass destructor.
- */
- void ReferenceCountedObject_zeroWeakPointers();
-
- virtual ~ReferenceCountedObject();
-
-
- /**
- Note: copies will initially start out with 0
- references and 0 weak references like any other object.
- */
- ReferenceCountedObject(const ReferenceCountedObject& notUsed);
-
- ReferenceCountedObject& operator=(const ReferenceCountedObject& other);
-};
-
-
-
-/**
- Use ReferenceCountedPointer<T> in place of T* in your program.
- T must subclass ReferenceCountedObject.
-@deprecated To be replaced by boost::shared_ptr in 7.0
- */
-template <class T>
-class ReferenceCountedPointer {
-private:
-
- T* m_pointer;
-
-public:
- typedef T element_type;
-
- inline T* pointer() const {
- return m_pointer;
- }
-
-private:
-
- /** Nulls out the pointer and drops a reference. If the reference
- count hits zero. */
- void zeroPointer() {
- if (m_pointer != NULL) {
-
- ReferenceCountedObject* pointer = ((ReferenceCountedObject*)m_pointer);
- debugAssert(G3D::isValidHeapPointer(m_pointer));
- debugAssertM(pointer->ReferenceCountedObject_refCount.value() > 0,
- "Dangling reference detected.");
-
- // Only delete if this instance caused the count to hit
- // exactly zero. If there is a race condition, the value
- // may be zero after decrement returns, but only one of
- // the instances will get a zero return value.
- if (pointer->ReferenceCountedObject_refCount.decrement() == 0) {
- // We held the last reference, so delete the object.
- // This test is threadsafe because there is no way for
- // the reference count to increase after the last
- // reference was dropped (assuming the application does
- // not voilate the class abstraction).
- //debugPrintf(" delete 0x%x\n", m_pointer);
-
- // We must zero the weak pointers *before* deletion in case there
- // are cycles of weak references.
- // Note that since there are no strong references at this point,
- // it is perfectly fair to zero the weak pointers anyway.
- pointer->ReferenceCountedObject_zeroWeakPointers();
- delete pointer;
- }
-
- m_pointer = NULL;
- }
- }
-
- /** Non-atomic (except for the referencec increment). Can only be
- called in contexts like the copy constructor or initial
- constructor where it is known that the reference count will
- not hit zero on some other thread. */
- void setPointer(T* x) {
- if (x != m_pointer) {
- zeroPointer();
-
- if (x != NULL) {
- debugAssert(G3D::isValidHeapPointer(x));
-
- m_pointer = x;
-
- // Note that the ref count can be zero if this is the
- // first pointer to it
- ReferenceCountedObject* pointer = (ReferenceCountedObject*)m_pointer;
- debugAssertM(pointer->ReferenceCountedObject_refCount.value() >= 0,
- "Negative reference count detected.");
- pointer->ReferenceCountedObject_refCount.increment();
- }
- }
- }
-
-public:
-
- inline ReferenceCountedPointer() : m_pointer(NULL) {}
- /**
- Allow silent cast <i>to</i> the base class.
-
- <pre>
- SubRef s = new Sub();
- BaseRef b = s;
- </pre>
-
- i.e., compile-time subtyping rule
- RCP&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <I>S</I>
- */
- template <class S>
- inline ReferenceCountedPointer(const ReferenceCountedPointer<S>& p) :
- m_pointer(NULL) {
- setPointer(p.pointer());
- }
-
-# if (! defined(MSC_VER) || (MSC_VER >= 1300))
- /**
- Explicit cast to a subclass. Acts like dynamic cast; the result will be NULL if
- the cast cannot succeed. Not supported on VC6.
- <pre>
- SubRef s = new Sub();
- BaseRef b = s;
- s = b.downcast<Sub>(); // Note that the template argument is the object type, not the pointer type.
- </pre>
- */
- template <class S>
- ReferenceCountedPointer<S> downcast() {
- return ReferenceCountedPointer<S>(dynamic_cast<S*>(m_pointer));
- }
-
- template <class S>
- const ReferenceCountedPointer<S> downcast() const {
- return ReferenceCountedPointer<S>(dynamic_cast<const S*>(m_pointer));
- }
-# endif
-
- // We need an explicit version of the copy constructor as well or
- // the default copy constructor will be used.
- inline ReferenceCountedPointer(const ReferenceCountedPointer<T>& p) : m_pointer(NULL) {
- setPointer(p.m_pointer);
- }
-
- /** Allows construction from a raw pointer. That object will thereafter be
- reference counted -- do not call delete on it.
-
- Use of const allows downcast on const references */
- inline ReferenceCountedPointer(const T* p) : m_pointer(NULL) {
- // only const constructor is defined to remove ambiguity using NULL
- setPointer(const_cast<T*>(p));
- }
-
-
- inline ~ReferenceCountedPointer() {
- zeroPointer();
- }
-
- inline size_t hashCode() const {
- return reinterpret_cast<size_t>(m_pointer);;
- }
-
- inline const ReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& p) {
- setPointer(p.m_pointer);
- return *this;
- }
-
- inline ReferenceCountedPointer<T>& operator=(T* p) {
- setPointer(p);
- return *this;
- }
-
- inline bool operator==(const ReferenceCountedPointer<T>& y) const {
- return (m_pointer == y.m_pointer);
- }
-
- inline bool operator!=(const ReferenceCountedPointer<T>& y) const {
- return (m_pointer != y.m_pointer);
- }
-
- bool operator < (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer < y.m_pointer);
- }
-
- bool operator > (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer > y.m_pointer);
- }
-
- bool operator <= (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer <= y.m_pointer);
- }
-
- bool operator >= (const ReferenceCountedPointer<T>& y) const {
- return (m_pointer >= y.m_pointer);
- }
-
- inline T& operator*() const {
- debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
- return (*m_pointer);
- }
-
- inline T* operator->() const {
- debugAssertM(m_pointer != NULL, "Dereferenced a NULL ReferenceCountedPointer");
- return m_pointer;
- }
-
- inline bool isNull() const {
- return (m_pointer == NULL);
- }
-
- inline bool notNull() const {
- return (m_pointer != NULL);
- }
-
- // TODO: distinguish between last strong and last any pointer
- /**
- Returns true if this is the last reference to an object.
- Useful for flushing memoization caches-- a cache that holds the last
- reference is unnecessarily keeping an object alive.
-
- <b>Not threadsafe.</b>
-
- @deprecated Use WeakReferenceCountedPointer for caches
- */
- inline int isLastReference() const {
- return (m_pointer->ReferenceCountedObject_refCount.value() == 1);
- }
-};
-
-
-/**
- A weak pointer allows the object it references to be garbage collected.
- Weak pointers are commonly used in caches, where it is important to hold
- a pointer to an object without keeping that object alive solely for the
- cache's benefit (i.e., the object can be collected as soon as all
- pointers to it <B>outside</B> the cache are gone). They are also convenient
- for adding back-pointers in tree and list structures.
-
- Weak pointers may become NULL at any point (when their target is collected).
- Therefore the only way to reference the target is to convert to a strong
- pointer and then check that it is not NULL.
-
-@deprecated To be replaced by boost::weak_ptr in 7.0
- */
-template <class T>
-class WeakReferenceCountedPointer : public _WeakPtr {
-private:
-
- /** NULL if the object has been collected. */
- T* pointer;
-
-public:
- /**
- Creates a strong pointer, which prevents the object from being
- garbage collected. The strong pointer may be NULL, which means
- that the underlying.
- */
- // There is intentionally no way to check if the
- // WeakReferenceCountedPointer has a null reference without
- // creating a strong pointer since there is no safe way to use
- // that information-- the pointer could be collected by a
- // subsequent statement.
- ReferenceCountedPointer<T> createStrongPtr() const {
- // TODO: What if the object's destructor is called while we
- // are in this method?
- return ReferenceCountedPointer<T>(pointer);
- }
-
-private:
-
- /** Thread issues: safe because this is only called when another
- object is guaranteed to keep p alive for the duration of this
- call. */
- void setPointer(T* p) {
- // TODO: must prevent the object from being collected while in
- // this method
-
- zeroPointer();
- pointer = p;
-
- if (pointer != NULL) {
- // TODO: threadsafe: must update the list atomically
-
- // Add myself to the head of my target's list of weak pointers
- _WeakPtrLinkedList* head =
- new _WeakPtrLinkedList
- (this,
- pointer->ReferenceCountedObject_weakPointer);
-
- pointer->ReferenceCountedObject_weakPointer = head;
- } else {
-
- }
- }
-
-
- /**
- Removes this from its target's list of weak pointers. Called
- when the weak pointer goes out of scope.
-
- Thread issues: depends on the thread safety of createStrongPtr.
- */
- void zeroPointer() {
- // Grab a strong reference to prevent the object from being collected while we
- // are traversing its list.
- ReferenceCountedPointer<T> strong = createStrongPtr();
-
- // If the following test fails then the object was collected before we
- // reached it.
- if (strong.notNull()) {
- debugAssertM(((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer != NULL,
- "Weak pointer exists without a backpointer from the object.");
-
- // Remove myself from my target's list of weak pointers
- _WeakPtrLinkedList** node = &((ReferenceCountedObject*)pointer)->ReferenceCountedObject_weakPointer;
- while ((*node)->weakPtr != this) {
- node = &((*node)->next);
- debugAssertM(*node != NULL,
- "Weak pointer exists without a backpointer from the object (2).");
- }
-
- // Node must now point at the node for me. Remove node and
- // close the linked list behind it.
- _WeakPtrLinkedList* temp = *node;
- *node = temp->next;
-
- // Now delete the node corresponding to me
- delete temp;
- }
-
- pointer = NULL;
- }
-
-public:
-
- WeakReferenceCountedPointer() : pointer(0) {}
-
- /**
- Allow compile time subtyping rule
- RCP&lt;<I>T</I>&gt; &lt;: RCP&lt;<I>S</I>&gt; if <I>T</I> &lt;: <I>S</I>
- */
- template <class S>
- inline WeakReferenceCountedPointer(const WeakReferenceCountedPointer<S>& p) : pointer(0) {
- // Threadsafe: the object cannot be collected while the other pointer exists.
- setPointer(p.pointer);
- }
-
- template <class S>
- inline WeakReferenceCountedPointer(const ReferenceCountedPointer<S>& p) : pointer(0) {
- // Threadsafe: the object cannot be collected while the other
- // pointer exists.
- setPointer(p.pointer());
- }
-
- // Gets called a *lot* when weak pointers are on the stack
- WeakReferenceCountedPointer(
- const WeakReferenceCountedPointer<T>& weakPtr) : pointer(0) {
- setPointer(weakPtr.pointer);
- }
-
- WeakReferenceCountedPointer(
- const ReferenceCountedPointer<T>& strongPtr) : pointer(0) {
- setPointer(strongPtr.pointer());
- }
-
- ~WeakReferenceCountedPointer() {
- zeroPointer();
- }
-
- WeakReferenceCountedPointer<T>& operator=(const WeakReferenceCountedPointer<T>& other) {
- // Threadsafe: the object cannot be collected while the other pointer exists.
-
- // I now point at other's target
- setPointer(other.pointer);
-
- return *this;
- }
-
- WeakReferenceCountedPointer<T>& operator=(const ReferenceCountedPointer<T>& other) {
-
- // Threadsafe: the object cannot be collected while the other pointer exists.
-
- // I now point at other's target
- setPointer(other.pointer());
-
- return *this;
- }
-
- bool operator==(const WeakReferenceCountedPointer<T>& other) const {
- return pointer == other.pointer;
- }
-
- bool operator!=(const WeakReferenceCountedPointer<T>& other) const {
- return pointer != other.pointer;
- }
-
- bool operator < (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer < y.pointer);
- }
-
- bool operator > (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer > y.pointer);
- }
-
- bool operator <= (const WeakReferenceCountedPointer<T>& y) const {
- return (pointer <= y.pointer);
- }
-
- bool operator >= (const ReferenceCountedPointer<T>& y) const {
- return (pointer >= y.pointer);
- }
-
-protected:
+template<class T>
+bool notNull(const ReferenceCountedPointer<T>& ptr) {
+ return (bool)ptr;
+}
- /** Invoked by the destructor on ReferenceCountedPointer. */
- void objectCollected() {
- debugAssertM(pointer != NULL,
- "Removed a weak pointer twice.");
- pointer = NULL;
- }
+template<class T>
+bool isNull(const T* ptr) {
+ return ptr == NULL;
+}
-};
+template<class T>
+bool notNull(const T* ptr) {
+ return ptr != NULL;
+}
} // namespace
diff --git a/dep/g3dlite/include/G3D/RegistryUtil.h b/dep/g3dlite/include/G3D/RegistryUtil.h
index 4b47be5f4bd..bd728562f10 100644
--- a/dep/g3dlite/include/G3D/RegistryUtil.h
+++ b/dep/g3dlite/include/G3D/RegistryUtil.h
@@ -15,7 +15,7 @@
#include "G3D/g3dmath.h"
// This file is only used on Windows
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <string>
@@ -92,6 +92,6 @@ public:
} // namespace G3D
-#endif // G3D_WIN32
+#endif // G3D_WINDOWS
#endif // G3D_REGISTRYTUIL_H
diff --git a/dep/g3dlite/include/G3D/Set.h b/dep/g3dlite/include/G3D/Set.h
index 0ea96b880cf..abad5e44e21 100644
--- a/dep/g3dlite/include/G3D/Set.h
+++ b/dep/g3dlite/include/G3D/Set.h
@@ -125,8 +125,13 @@ public:
return !(*this == other);
}
+ bool isValid() const {
+ return it.isValid();
+ }
+
+ /** @deprecated Use isValid */
bool hasMore() const {
- return it.hasMore();
+ return it.isValid();
}
bool operator==(const Iterator& other) const {
diff --git a/dep/g3dlite/include/G3D/SmallArray.h b/dep/g3dlite/include/G3D/SmallArray.h
index 900d2335ee1..f738e1e8d58 100644
--- a/dep/g3dlite/include/G3D/SmallArray.h
+++ b/dep/g3dlite/include/G3D/SmallArray.h
@@ -1,10 +1,10 @@
/**
- @file SmallArray.h
+ \file G3D/SmallArray.h
- @created 2009-04-26
- @edited 2010-02-26
+ \created 2009-04-26
+ \edited 2012-07-23
- Copyright 2000-2010, Morgan McGuire, http://graphics.cs.williams.edu
+ Copyright 2000-2012, Morgan McGuire, http://graphics.cs.williams.edu
All rights reserved.
*/
#ifndef G3D_SmallArray_h
@@ -83,6 +83,35 @@ public:
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) {
@@ -139,8 +168,8 @@ public:
return m_rest.contains(value);
}
- template<int MIN_ELEMENTS, int MIN_BYTES>
- SmallArray<T, N>& operator=(const Array<T, MIN_ELEMENTS, MIN_BYTES>& src) {
+ 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];
@@ -148,13 +177,13 @@ public:
return *this;
}
- inline const T& last() const {
- return (*this)[size() - 1];
- }
+ inline const T& last() const {
+ return (*this)[size() - 1];
+ }
- inline T& last() {
- return (*this)[size() - 1];
- }
+ inline T& last() {
+ return (*this)[size() - 1];
+ }
};
}
diff --git a/dep/g3dlite/include/G3D/SpawnBehavior.h b/dep/g3dlite/include/G3D/SpawnBehavior.h
new file mode 100644
index 00000000000..25f68c0a644
--- /dev/null
+++ b/dep/g3dlite/include/G3D/SpawnBehavior.h
@@ -0,0 +1,6 @@
+#ifndef SpawnBehavior_h
+#define SpawnBehavior_h
+namespace G3D {
+enum SpawnBehavior {USE_NEW_THREAD, USE_CURRENT_THREAD};
+}
+#endif
diff --git a/dep/g3dlite/include/G3D/Sphere.h b/dep/g3dlite/include/G3D/Sphere.h
index d1448261d9f..fa060f0c15d 100644
--- a/dep/g3dlite/include/G3D/Sphere.h
+++ b/dep/g3dlite/include/G3D/Sphere.h
@@ -1,16 +1,16 @@
/**
- @file Sphere.h
+ \file G3D/Sphere.h
Sphere class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2008-10-07
+ \created 2001-06-02
+ \edited 2011-02-07
*/
-#ifndef G3D_SPHERE_H
-#define G3D_SPHERE_H
+#ifndef G3D_Sphere_h
+#define G3D_Sphere_h
#include "G3D/platform.h"
#include "G3D/Vector3.h"
@@ -27,28 +27,36 @@ private:
static int32 dummy;
public:
- Vector3 center;
+ Point3 center;
float radius;
- Sphere() {
- center = Vector3::zero();
- radius = 0;
+ 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);
- Sphere(
- const Vector3& center,
- float radius) {
+ /** Format is one of:
+ - Sphere(point, radius)
+ - Sphere(radius)
+ */
+ explicit Sphere(const class Any& a);
+
+ Any toAny() const;
- this->center = center;
- this->radius = radius;
+ 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);
}
@@ -61,7 +69,7 @@ public:
Returns true if point is less than or equal to radius away from
the center.
*/
- bool contains(const Vector3& point) const;
+ bool contains(const Point3& point) const;
bool contains(const Sphere& other) const;
@@ -71,7 +79,7 @@ public:
bool culledBy(
const class Plane* plane,
int numPlanes,
- int32& cullingPlaneIndex,
+ int32& cullingPlaneIndex,
const uint32 testMask,
uint32& childMask) const;
@@ -88,18 +96,18 @@ public:
See AABox::culledBy
*/
bool culledBy(
- const Array<Plane>& plane,
- int32& cullingPlaneIndex,
- const uint32 testMask,
+ 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;
+ const Array<Plane>& plane,
+ int32& cullingPlaneIndex = dummy,
+ const uint32 testMask = 0xFFFFFFFF) const;
virtual std::string toString() const;
@@ -110,12 +118,12 @@ public:
/**
Uniformly distributed on the surface.
*/
- Vector3 randomSurfacePoint() const;
+ Point3 randomSurfacePoint() const;
/**
Uniformly distributed on the interior (includes surface)
*/
- Vector3 randomInteriorPoint() const;
+ Point3 randomInteriorPoint() const;
void getBounds(class AABox& out) const;
diff --git a/dep/g3dlite/include/G3D/Spline.h b/dep/g3dlite/include/G3D/Spline.h
index 89f89194f1e..360de167675 100644
--- a/dep/g3dlite/include/G3D/Spline.h
+++ b/dep/g3dlite/include/G3D/Spline.h
@@ -1,17 +1,19 @@
/**
- @file Spline.h
+ \file G3D/Spline.h
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
*/
-#ifndef G3D_SPLINE_H
-#define G3D_SPLINE_H
+#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 {
@@ -23,10 +25,12 @@ public:
number of elements as Spline::control. */
Array<float> time;
- /** If cyclic, then the control points will be assumed to wrap around.
- If not cyclic, then the tangents at the ends of the spline
- point to the final control points.*/
- bool cyclic;
+ /** 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
@@ -36,8 +40,13 @@ public:
time[time.size() - 1] - time[time.size() - 2]) / 2.
*/
float finalInterval;
+
+ SplineInterpolationMode interpolationMode;
- SplineBase() : cyclic(true), finalInterval(-1) {}
+ SplineBase() :
+ extrapolationMode(SplineExtrapolationMode::CYCLIC),
+ finalInterval(-1),
+ interpolationMode(SplineInterpolationMode::CUBIC) {}
virtual ~SplineBase() {}
@@ -144,11 +153,7 @@ public:
break;
case 1:
- if (time[0] == 0) {
- append(1, c);
- } else {
- append(time[0], c);
- }
+ append(time[0] + 1, c);
break;
default:
@@ -192,7 +197,7 @@ public:
if (N == 0) {
c = zero;
t = 0;
- } else if (cyclic) {
+ } else if (extrapolationMode == SplineExtrapolationMode::CYCLIC) {
c = control[iWrap(i, N)];
if (i < 0) {
@@ -222,9 +227,16 @@ public:
// Step away from control point 0
float dt = time[1] - time[0];
- // Extrapolate (note; i is negative)
- c = control[1] * float(i) + control[0] * float(1 - i);
- correct(c);
+ 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 {
@@ -239,9 +251,17 @@ public:
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
- c = control[N - 1] * float(i - N + 2) + control[N - 2] * -float(i - N + 1);
- correct(c);
t = time[N - 1] + dt * (i - N + 1);
} else {
@@ -279,8 +299,47 @@ protected:
/** 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
@@ -313,6 +372,22 @@ public:
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];
@@ -325,13 +400,6 @@ public:
// Compute the weights on each of the control points.
const Vector4& weights = uvec * basis;
- // Compute the weighted sum of the neighboring control points.
- Control sum;
-
- const Control& p0 = p[0];
- const Control& p1 = p[1];
- const Control& p2 = p[2];
- const Control& p3 = p[3];
// The factor of 1/2 from averaging two time intervals is
// already factored into the basis
diff --git a/dep/g3dlite/include/G3D/SplineExtrapolationMode.h b/dep/g3dlite/include/G3D/SplineExtrapolationMode.h
new file mode 100644
index 00000000000..b5cdc6fb81c
--- /dev/null
+++ b/dep/g3dlite/include/G3D/SplineExtrapolationMode.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/Stopwatch.h b/dep/g3dlite/include/G3D/Stopwatch.h
index 3f2aa9c8d86..48c223b5ba5 100644
--- a/dep/g3dlite/include/G3D/Stopwatch.h
+++ b/dep/g3dlite/include/G3D/Stopwatch.h
@@ -46,6 +46,9 @@ class Stopwatch {
private:
std::string myName;
+
+ bool m_enabled;
+
double startTime;
std::string prevMark;
double prevTime;
@@ -85,6 +88,15 @@ 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 {
@@ -130,7 +142,10 @@ public:
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. */
+ 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 = "");
};
diff --git a/dep/g3dlite/include/G3D/System.h b/dep/g3dlite/include/G3D/System.h
index 45aef1549b6..4624dd91647 100644
--- a/dep/g3dlite/include/G3D/System.h
+++ b/dep/g3dlite/include/G3D/System.h
@@ -1,14 +1,14 @@
/**
- @file System.h
+ \file System.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \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
+ \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 2008-10-14
+ \created 2003-01-25
+ \edited 2012-10-02
*/
#ifndef G3D_System_h
@@ -18,28 +18,16 @@
#include "G3D/g3dmath.h"
#include "G3D/G3DGameUnits.h"
#include "G3D/BinaryFormat.h"
+#include "G3D/FileNotFound.h"
#include <string>
-#ifdef G3D_LINUX
-# include <sys/socket.h>
-#endif
#ifdef G3D_OSX
+#define Zone OSX_Zone
# include <CoreServices/CoreServices.h>
#endif
namespace G3D {
-
-/**
- Routine used by the demos to find the data. Searches in
- ../data, ../../data, etc. up to 5 levels back. Checks
- common locations like \verbatim c:\libraries\g3d-<version>\data \endverbatim
- and some hard-coded paths on the Brown University file
- system.
-
- @deprecated
- */
-std::string demoFindData(bool errorIfNotFound = true);
-
+
/** G3D, SDL, and IJG libraries require license documentation
to be distributed with your program. This generates the
string that must appear in your documentation.
@@ -118,7 +106,7 @@ private:
std::string m_cpuArch;
std::string m_operatingSystem;
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
/** Used by getTick() for timing */
LARGE_INTEGER m_start;
LARGE_INTEGER m_counterFrequency;
@@ -167,7 +155,6 @@ private:
*/
static void cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg);
- void init();
/** Called from init() */
void getStandardProcessorExtensions();
@@ -175,7 +162,12 @@ private:
/** 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.*/
@@ -243,16 +235,13 @@ public:
*/
static std::string currentDateString();
- /**
- Guarantees that the start of the array is aligned to the
- specified number of bytes.
- */
- static void* alignedMalloc(size_t bytes, size_t alignment);
-
+ /** 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 ::malloc or
- new.
+ kilobytes). Can be 10x to 100x faster than calling \c malloc or
+ \c new.
The result must be freed with free.
@@ -289,6 +278,12 @@ public:
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);
@@ -370,6 +365,7 @@ public:
/**
To count the number of cycles a given operation takes:
+ \htmlonly
<PRE>
unsigned long count;
System::beginCycleCount(count);
@@ -377,11 +373,12 @@ public:
System::endCycleCount(count);
// count now contains the cycle count for the intervening operation.
</PRE>
+ \endhtmlonly
*/
- /* static void beginCycleCount(uint64& cycleCount);
+ static void beginCycleCount(uint64& cycleCount);
static void endCycleCount(uint64& cycleCount);
- static uint64 getCycleCount(); */
+ static uint64 getCycleCount();
inline static void setOutOfMemoryCallback(OutOfMemoryCallback c) {
instance().m_outOfMemoryCallback = c;
@@ -404,7 +401,7 @@ public:
/** 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);
@@ -412,25 +409,53 @@ public:
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
+ (class TextOutput& t);
- static void describeSystem(
- std::string& s);
-
- /** On Win32, returns the clipboard text contents. Does nothing on other
- platforms (yet) */
- static std::string getClipboardText();
-
- /** Copies the text to the clipboard on Win32. */
- static void setClipboardText(const std::string& s);
+ 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 errorIfNotFound = true);
+ 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.
@@ -441,22 +466,33 @@ public:
};
-/* don't need that for MaNGOS, not portable to Win64...
-#ifdef _MSC_VER
- 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;
- }
+#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)
@@ -475,13 +511,13 @@ public:
#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
-
+ //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();
+ //return (uint64) mach_absolute_time();
}
#endif
@@ -496,15 +532,20 @@ inline void System::endCycleCount(uint64& cycleCount) {
cycleCount = getCycleCount() - cycleCount;
#else
AbsoluteTime end = UpTime();
- Nanoseconds diffNS =
+ Nanoseconds diffNS =
AbsoluteDeltaToNanoseconds(end, UInt64ToUnsignedWide(cycleCount));
- cycleCount =
- (uint64) ((double) (instance().m_OSXCPUSpeed) *
+ cycleCount =
+ (uint64) ((double) (instance().m_OSXCPUSpeed) *
(double) UnsignedWideToUInt64(diffNS) * instance().m_secondsPerNS);
#endif
}
- */
+
} // namespace
+
+#ifdef G3D_OSX
+#undef Zone
+#endif
+
#endif
diff --git a/dep/g3dlite/include/G3D/Table.h b/dep/g3dlite/include/G3D/Table.h
index ab0b114b1c4..b8653fdcc9d 100644
--- a/dep/g3dlite/include/G3D/Table.h
+++ b/dep/g3dlite/include/G3D/Table.h
@@ -5,8 +5,8 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-04-22
- @edited 2010-01-28
- Copyright 2000-2010, Morgan McGuire.
+ @edited 2013-01-22
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -90,7 +90,8 @@ namespace G3D {
};
</PRE>
- and rely on the default enum operator==.
+ And rely on the default enum operator==.
+
Periodically check that debugGetLoad() is low (> 0.1). When it gets near
1.0 your hash function is badly designed and maps too many inputs to
@@ -132,10 +133,12 @@ private:
// Private to require use of the allocator
Node(const Key& k, const Value& v, size_t h, Node* n)
: entry(k, v), hashCode(h), next(n) {
+ debugAssert((next == NULL) || isValidHeapPointer(next));
}
Node(const Key& k, size_t h, Node* n)
: entry(k), hashCode(h), next(n) {
+ debugAssert((next == NULL) || isValidHeapPointer(next));
}
public:
@@ -213,9 +216,9 @@ private:
// Allocate a new m_bucket array with the new size
m_bucket = (Node**)alloc(sizeof(Node*) * newSize);
+ alwaysAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory.");
// Set all pointers to NULL
System::memset(m_bucket, 0, newSize * sizeof(Node*));
- debugAssertM(m_bucket != NULL, "MemoryManager::alloc returned NULL. Out of memory.");
// Move each node to its new hash location
for (size_t b = 0; b < m_numBuckets; ++b) {
Node* node = oldBucket[b];
@@ -274,7 +277,7 @@ private:
void freeMemory() {
checkIntegrity();
- for (size_t b = 0; b < m_numBuckets; b++) {
+ for (size_t b = 0; b < m_numBuckets; ++b) {
Node* node = m_bucket[b];
while (node != NULL) {
Node* next = node->next;
@@ -357,7 +360,7 @@ public:
size_t debugGetDeepestBucketSize() const {
size_t deepest = 0;
- for (size_t b = 0; b < m_numBuckets; b++) {
+ for (size_t b = 0; b < m_numBuckets; ++b) {
size_t count = 0;
Node* node = m_bucket[b];
while (node != NULL) {
@@ -377,21 +380,16 @@ public:
Returns the average size of non-empty buckets.
*/
float debugGetAverageBucketSize() const {
- size_t num = 0;
- size_t count = 0;
+ uint64 num = 0;
- for (size_t b = 0; b < m_numBuckets; b++) {
+ for (size_t b = 0; b < m_numBuckets; ++b) {
Node* node = m_bucket[b];
if (node != NULL) {
++num;
- while (node != NULL) {
- node = node->next;
- ++count;
- }
}
}
- return (float)((double)count / num);
+ return (float)((double)size() / num);
}
/**
@@ -402,7 +400,7 @@ public:
many keys to the same code.
*/
double debugGetLoad() const {
- return debugGetDeepestBucketSize() / (double)size();
+ return (double)size() / m_numBuckets;
}
/**
@@ -428,7 +426,7 @@ public:
Linked list node.
*/
Node* node;
- ThisType* table;
+
size_t m_numBuckets;
Node** m_bucket;
bool isDone;
@@ -436,13 +434,14 @@ public:
/**
Creates the end iterator.
*/
- Iterator(const ThisType* table) : table(const_cast<ThisType*>(table)) {
+ Iterator() : index(0), node(NULL), m_bucket(NULL) {
isDone = true;
}
- Iterator(const ThisType* table, size_t m_numBuckets, Node** m_bucket) :
- table(const_cast<ThisType*>(table)),
- m_numBuckets(m_numBuckets),
+ Iterator(size_t numBuckets, Node** m_bucket) :
+ index(0),
+ node(NULL),
+ m_numBuckets(numBuckets),
m_bucket(m_bucket) {
if (m_numBuckets == 0) {
@@ -451,26 +450,38 @@ public:
return;
}
+# ifdef G3D_DEBUG
+ for (unsigned int i = 0; i < m_numBuckets; ++i) {
+ debugAssert((m_bucket[i] == NULL) || isValidHeapPointer(m_bucket[i]));
+ }
+# endif
+
index = 0;
node = m_bucket[index];
+ debugAssert((node == NULL) || isValidHeapPointer(node));
isDone = false;
findNext();
+ debugAssert((node == NULL) || isValidHeapPointer(node));
}
/**
- Finds the next element, setting isDone if one can't be found.
- Looks at the current element first.
+ If node is NULL, then finds the next element by searching through the bucket array.
+ Sets isDone if no more nodes are available.
*/
void findNext() {
while (node == NULL) {
- index++;
+ ++index;
if (index >= m_numBuckets) {
+ m_bucket = NULL;
+ index = 0;
isDone = true;
- break;
+ return;
} else {
node = m_bucket[index];
+ debugAssert((node == NULL) || isValidHeapPointer(node));
}
}
+ debugAssert(isValidHeapPointer(node));
}
public:
@@ -481,12 +492,9 @@ public:
bool operator==(const Iterator& other) const {
if (other.isDone || isDone) {
// Common case; check against isDone.
- return (isDone == other.isDone) && (other.table == table);
+ return (isDone == other.isDone);
} else {
- return
- (table == other.table) &&
- (node == other.node) &&
- (index == other.index);
+ return (node == other.node) && (index == other.index);
}
}
@@ -494,8 +502,13 @@ public:
Pre increment.
*/
Iterator& operator++() {
+ debugAssert(! isDone);
+ debugAssert(node != NULL);
+ debugAssert(isValidHeapPointer(node));
+ debugAssert((node->next == NULL) || isValidHeapPointer(node->next));
node = node->next;
findNext();
+ debugAssert(isDone || isValidHeapPointer(node));
return *this;
}
@@ -512,17 +525,32 @@ public:
return node->entry;
}
+ const Value& value() const {
+ return node->entry.value;
+ }
+
+ const Key& key() const {
+ return node->entry.key;
+ }
+
Entry* operator->() const {
+ debugAssert(isValidHeapPointer(node));
return &(node->entry);
}
operator Entry*() const {
+ debugAssert(isValidHeapPointer(node));
return &(node->entry);
}
- bool hasMore() const {
- return ! isDone;
- }
+ bool isValid() const {
+ return ! isDone;
+ }
+
+ /** @deprecated Use isValid */
+ bool hasMore() const {
+ return ! isDone;
+ }
};
@@ -532,7 +560,7 @@ public:
the next element. Do not modify the table while iterating.
*/
Iterator begin() const {
- return Iterator(this, m_numBuckets, m_bucket);
+ return Iterator(m_numBuckets, m_bucket);
}
/**
@@ -540,11 +568,12 @@ public:
element.
*/
const Iterator end() const {
- return Iterator(this);
+ return Iterator();
}
/**
- Removes all elements
+ Removes all elements. Guaranteed to free all memory associated with
+ the table.
*/
void clear() {
freeMemory();
@@ -578,20 +607,21 @@ private:
if (m_numBuckets == 0) {
return false;
}
- size_t code = HashFunc::hashCode(key);
- size_t b = code % m_numBuckets;
+
+ const size_t code = HashFunc::hashCode(key);
+ const size_t b = code % m_numBuckets;
- // Go to the m_bucket
- Node* n = m_bucket[b];
+ // Go to the m_bucket
+ Node* n = m_bucket[b];
- if (n == NULL) {
- return false;
- }
+ if (n == NULL) {
+ return false;
+ }
- Node* previous = NULL;
+ Node* previous = NULL;
- // Try to find the node
- do {
+ // Try to find the node
+ do {
if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
// This is the node; remove it
@@ -609,6 +639,8 @@ private:
// Delete the node
Node::destroy(n, m_memoryManager);
--m_size;
+
+ //checkIntegrity();
return true;
}
@@ -616,8 +648,8 @@ private:
n = n->next;
} while (n != NULL);
+ //checkIntegrity();
return false;
- //alwaysAssertM(false, "Tried to remove a key that was not in the table.");
}
public:
@@ -658,7 +690,7 @@ private:
node = node->next;
}
- return NULL;
+ return NULL;
}
public:
@@ -733,7 +765,6 @@ public:
}
-
/** Called by getCreate() and set()
\param created Set to true if the entry was created by this method.
@@ -756,6 +787,7 @@ public:
m_bucket[b] = Node::create(key, code, NULL, m_memoryManager);
++m_size;
created = true;
+ //checkIntegrity();
return m_bucket[b]->entry;
}
@@ -772,6 +804,7 @@ public:
if ((code == n->hashCode) && EqualsFunc::equals(n->entry.key, key)) {
// This is the a pre-existing node
+ //checkIntegrity();
return n->entry;
}
@@ -779,12 +812,18 @@ public:
++bucketLength;
} while (n != NULL);
+ // Allow the load factor to rise as the table gets huge
+ const int bucketsPerElement =
+ (m_size > 50000) ? 3 :
+ ((m_size > 10000) ? 5 :
+ ((m_size > 5000) ? 10 : 15));
+
const size_t maxBucketLength = 3;
// (Don't bother changing the size of the table if all entries
// have the same hashcode--they'll still collide)
if ((bucketLength > maxBucketLength) &&
! allSameCode &&
- (m_numBuckets < m_size * 15)) {
+ (m_numBuckets < m_size * bucketsPerElement)) {
// This m_bucket was really large; rehash if all elements
// don't have the same hashcode the number of buckets is
@@ -807,8 +846,10 @@ public:
m_bucket[b] = Node::create(key, code, m_bucket[b], m_memoryManager);
++m_size;
created = true;
+
+ //checkIntegrity();
return m_bucket[b]->entry;
- }
+ }
Entry& getCreateEntry(const Key& key) {
bool ignore;
@@ -871,7 +912,7 @@ public:
void getKeys(Array<Key>& keyArray) const {
keyArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
- for (size_t i = 0; i < m_numBuckets; i++) {
+ for (size_t i = 0; i < m_numBuckets; ++i) {
Node* node = m_bucket[i];
while (node != NULL) {
keyArray.append(node->entry.key);
@@ -880,14 +921,27 @@ public:
}
}
+ /** Will contain duplicate values if they exist in the table. This array is parallel to the one returned by getKeys() if the table has not been modified. */
+ void getValues(Array<Value>& valueArray) const {
+ valueArray.resize(0, DONT_SHRINK_UNDERLYING_ARRAY);
+ for (size_t i = 0; i < m_numBuckets; ++i) {
+ Node* node = m_bucket[i];
+ while (node != NULL) {
+ valueArray.append(node->entry.value);
+ node = node->next;
+ }
+ }
+ }
+
/**
Calls delete on all of the keys and then clears the table.
*/
void deleteKeys() {
- for (size_t i = 0; i < m_numBuckets; i++) {
+ for (size_t i = 0; i < m_numBuckets; ++i) {
Node* node = m_bucket[i];
while (node != NULL) {
delete node->entry.key;
+ node->entry.key = NULL;
node = node->next;
}
}
@@ -912,6 +966,37 @@ public:
}
}
}
+
+ template<class H, class E>
+ bool operator==(const Table<Key, Value, H, E>& other) const {
+ if (size() != other.size()) {
+ return false;
+ }
+
+ for (Iterator it = begin(); it.hasMore(); ++it) {
+ const Value* v = other.getPointer(it->key);
+ if ((v == NULL) || (*v != it->value)) {
+ // Either the key did not exist or the value was not the same
+ return false;
+ }
+ }
+
+ // this and other have the same number of keys, so we don't
+ // have to check for extra keys in other.
+
+ return true;
+ }
+
+ template<class H, class E>
+ bool operator!=(const Table<Key, Value, H, E>& other) const {
+ return ! (*this == other);
+ }
+
+ void debugPrintStatus() {
+ debugPrintf("Deepest bucket size = %d\n", (int)debugGetDeepestBucketSize());
+ debugPrintf("Average bucket size = %g\n", debugGetAverageBucketSize());
+ debugPrintf("Load factor = %g\n", debugGetLoad());
+ }
};
} // namespace
diff --git a/dep/g3dlite/include/G3D/TextInput.h b/dep/g3dlite/include/G3D/TextInput.h
index 7aefb50ffa8..47cbe8c91f7 100644
--- a/dep/g3dlite/include/G3D/TextInput.h
+++ b/dep/g3dlite/include/G3D/TextInput.h
@@ -1,16 +1,16 @@
/**
- @file TextInput.h
+ \file G3D/TextInput.h
Simple text lexer/tokenizer.
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Based on a lexer written by Aaron Orenstein.
+ \cite Based on a lexer written by Aaron Orenstein.
- @created 2002-11-27
- @edited 2010-07-03
+ \created 2002-11-27
+ \edited 2013-03-25
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -148,7 +148,9 @@ public:
/**
- A simple style tokenizer for reading text files. TextInput handles a
+ \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,
@@ -191,7 +193,7 @@ public:
<B>Examples</B>
- <PRE>
+ \code
TextInput ti(TextInput::FROM_STRING, "name = \"Max\", height = 6");
Token t;
@@ -206,15 +208,15 @@ public:
std::string name = ti.read().sval;
ti.read();
- </PRE>
+ \endcode
- <PRE>
+ \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();
- </PRE>
+ \endcode
Assumes that the file is not modified once opened.
*/
@@ -329,14 +331,15 @@ public:
int startingLineNumberOffset;
/**
- Parse -1.#IND00 as the floating point number returned by
- nan(), -1.#INF00 as -G3D::inf(), and 1.#INF00 as G3D::inf().
-
+ 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();
@@ -349,6 +352,7 @@ public:
}
// ... similar cases for inf
</pre>
+ \endhtmlonly
If the single-comment character was #, the floating point
special format overrides the comment and will be parsed
@@ -398,9 +402,12 @@ public:
Settings();
};
-
+
private:
+ /** \sa pushSettings / popSettings */
+ Array<Settings> settingsStack;
+
std::deque<Token> stack;
/**
@@ -477,7 +484,7 @@ private:
Read the next token, returning an END token if no more input is
available.
*/
- Token nextToken();
+ void nextToken(Token& t);
/**
Helper for nextToken. Appends characters to t._string until the end
@@ -488,6 +495,8 @@ private:
*/
void parseQuotedString(unsigned char delimiter, Token& t);
+ void initFromString(const char* str, int len, const Settings& settings);
+
public:
class TokenException : public ParseError {
@@ -569,9 +578,25 @@ public:
*/
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
@@ -589,10 +614,13 @@ public:
*/
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) as a number or throws
+ /** 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.
@@ -608,6 +636,10 @@ public:
*/
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.
@@ -643,7 +675,7 @@ public:
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()
+ \sa readString(), readStringToken(), readUntilNewlineAsString(), readUntilDelimiterAsString()
*/
void readString(const std::string& s);
@@ -653,6 +685,12 @@ public:
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
@@ -734,6 +772,9 @@ public:
*/
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
diff --git a/dep/g3dlite/include/G3D/TextOutput.h b/dep/g3dlite/include/G3D/TextOutput.h
index 4c22b7d5653..b124f0b742b 100644
--- a/dep/g3dlite/include/G3D/TextOutput.h
+++ b/dep/g3dlite/include/G3D/TextOutput.h
@@ -1,16 +1,16 @@
/**
- @file TextOutput.h
+ \file G3D/TextOutput.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-06-21
- @edited 2006-10-24
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2004-06-21
+ \edited 2011-05-24
- Copyright 2000-2007, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_TEXTOUTPUT_H
-#define G3D_TEXTOUTPUT_H
+#ifndef G3D_TextOutput_h
+#define G3D_TextOutput_h
#include "G3D/platform.h"
#include "G3D/Array.h"
@@ -112,7 +112,7 @@ public:
convertNewlines(true),
trueSymbol("true"),
falseSymbol("false") {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
newlineStyle = NEWLINE_WINDOWS;
#else
newlineStyle = NEWLINE_UNIX;
@@ -156,6 +156,9 @@ private:
/** 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 */
@@ -175,6 +178,11 @@ public:
/** 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.
@@ -206,6 +214,9 @@ public:
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.)
@@ -213,6 +224,8 @@ public:
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.
*/
diff --git a/dep/g3dlite/include/G3D/ThreadSet.h b/dep/g3dlite/include/G3D/ThreadSet.h
index 121f1415a1d..5b78e44d6ee 100644
--- a/dep/g3dlite/include/G3D/ThreadSet.h
+++ b/dep/g3dlite/include/G3D/ThreadSet.h
@@ -1,14 +1,16 @@
-#ifndef G3D_THREADSET_H
-#define G3D_THREADSET_H
+#ifndef G3D_ThreadSet_h
+#define G3D_ThreadSet_h
#include "G3D/platform.h"
#include "G3D/Array.h"
#include "G3D/ReferenceCount.h"
-#include "G3D/GThread.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.
@@ -18,8 +20,8 @@ public:
/** Intended to allow future use with a template parameter.*/
typedef GThread Thread;
- typedef ReferenceCountedPointer<Thread> ThreadRef;
- typedef ReferenceCountedPointer<ThreadSet> Ref;
+ typedef shared_ptr<Thread> ThreadRef;
+ typedef shared_ptr<ThreadSet> Ref;
typedef Array<ThreadRef>::Iterator Iterator;
typedef Array<ThreadRef>::ConstIterator ConstIterator;
@@ -41,13 +43,14 @@ public:
/** 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.
+ @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(GThread::SpawnBehavior lastThreadBehavior = GThread::USE_NEW_THREAD) const;
+ void start(SpawnBehavior lastThreadBehavior = USE_NEW_THREAD) const;
/** Terminate all threads that are currently started */
void terminate() const;
diff --git a/dep/g3dlite/include/G3D/Triangle.h b/dep/g3dlite/include/G3D/Triangle.h
index 590dbaad946..f9ece956c30 100644
--- a/dep/g3dlite/include/G3D/Triangle.h
+++ b/dep/g3dlite/include/G3D/Triangle.h
@@ -1,19 +1,19 @@
/**
- @file Triangle.h
+ \file G3D/Triangle.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-04-05
- @edited 2008-10-06
+ \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
+ \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-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_TRIANGLE_H
-#define G3D_TRIANGLE_H
+#ifndef G3D_Triangle_h
+#define G3D_Triangle_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
@@ -55,19 +55,19 @@ private:
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);
+ void serialize(class BinaryOutput& b);
+ void deserialize(class BinaryInput& b);
Triangle();
- Triangle(const Vector3& v0, const Vector3& v1, const Vector3& v2);
+ Triangle(const Point3& v0, const Point3& v1, const Point3& v2);
~Triangle();
/** 0, 1, or 2 */
- inline const Vector3& vertex(int n) const {
+ inline const Point3& vertex(int n) const {
debugAssert((n >= 0) && (n < 3));
return _vertex[n];
}
@@ -91,15 +91,15 @@ public:
const Vector3& normal() const;
/** Barycenter */
- Vector3 center() const;
+ Point3 center() const;
const Plane& plane() const;
/** Returns a random point in the triangle. */
- Vector3 randomPoint() const;
+ Point3 randomPoint() const;
inline void getRandomSurfacePoint
- (Vector3& P,
+ (Point3& P,
Vector3& N = Vector3::ignore()) const {
P = randomPoint();
N = normal();
diff --git a/dep/g3dlite/include/G3D/UprightFrame.h b/dep/g3dlite/include/G3D/UprightFrame.h
index ad5157cb14b..696ab94df1d 100644
--- a/dep/g3dlite/include/G3D/UprightFrame.h
+++ b/dep/g3dlite/include/G3D/UprightFrame.h
@@ -1,25 +1,24 @@
/**
- @file UprightFrame.h
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \file G3D/UprightFrame.h
+ \author Morgan McGuire, http://graphics.cs.williams.edu
*/
-#ifndef G3D_UPRIGHTFRAME_H
-#define G3D_UPRIGHTFRAME_H
+#ifndef G3D_UprightFrame_h
+#define G3D_UprightFrame_h
#include "G3D/platform.h"
#include "G3D/Spline.h"
-#include "G3D/Vector3.h"
+#include "G3D/Any.h"
#include "G3D/CoordinateFrame.h"
namespace G3D {
/**
- 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.
+ \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
+ \sa G3D::CoordinateFrame, G3D::Matrix4, G3D::PhysicsFrame, G3D::UprightSpline, G3D::UprightSplineManipulator
*/
class UprightFrame {
public:
@@ -32,18 +31,32 @@ public:
/** In radians about the Y-axis */
float yaw;
- inline UprightFrame(const Vector3& t = Vector3::zero(), float p = 0, float y = 0)
+ 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);
- CoordinateFrame toCoordinateFrame() const;
+ Any toAny() const;
+
+ UprightFrame& operator=(const Any& any);
/** Supports implicit cast to CoordinateFrame */
- inline operator CoordinateFrame() const {
+ operator CoordinateFrame() const {
return toCoordinateFrame();
}
+ CoordinateFrame toCoordinateFrame() const;
+
/** Required for use with spline */
UprightFrame operator+(const UprightFrame& other) const;
@@ -61,8 +74,10 @@ public:
void deserialize(class BinaryInput& b);
};
-/** Shortest-path linear velocity spline for camera positions. Always keeps the camera from rolling.
-@sa G3D::UprightSplineManipulator, G3D::UprightFrame
+/**
+ \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:
@@ -72,10 +87,29 @@ protected:
}
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);
-
};
}
diff --git a/dep/g3dlite/include/G3D/Vector2.h b/dep/g3dlite/include/G3D/Vector2.h
index dba7353785e..65cf7fa8f2f 100644
--- a/dep/g3dlite/include/G3D/Vector2.h
+++ b/dep/g3dlite/include/G3D/Vector2.h
@@ -1,19 +1,19 @@
/**
- @file Vector2.h
+ \file G3D/Vector2.h
2D vector class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2008-11-30
+ \created 2001-06-02
+ \edited 2011-11-30
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_VECTOR2_H
-#define G3D_VECTOR2_H
+#ifndef G3D_Vector2_h
+#define G3D_Vector2_h
#include <string>
@@ -22,6 +22,7 @@
#include "G3D/Table.h"
#include "G3D/HashTrait.h"
#include "G3D/Vector2int16.h"
+#include "G3D/Vector2unorm16.h"
#include "G3D/Random.h"
namespace G3D {
@@ -29,6 +30,7 @@ namespace G3D {
class Vector2;
class Vector3;
class Vector4;
+class Vector2int32;
class Any;
/**
@@ -51,7 +53,7 @@ public:
Vector2(const Any& any);
/** Converts the Vector2 to an Any. */
- operator Any() const;
+ Any toAny() const;
/** Creates the zero vector */
Vector2();
@@ -62,6 +64,12 @@ public:
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);
@@ -83,6 +91,11 @@ public:
/** 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;
@@ -94,6 +107,11 @@ public:
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;
@@ -138,12 +156,19 @@ public:
// vector operations
- /** */
+ /** Magnitude of the vector */
float length() const;
- /** Returns a unit-length vector */
+ /**
+ 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.
@@ -155,15 +180,35 @@ public:
float squaredLength() const;
float dot(const Vector2& s) const;
- /**
- Make this vector have unit length and return the old length.
- If the vector length was less than tolerance, do not normalize.
- */
- float unitize(float fTolerance = 1e-06);
+ /** 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());
@@ -263,7 +308,8 @@ inline Vector2::Vector2 (const Vector2& rkVector) {
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];
@@ -385,6 +431,16 @@ inline Vector2 Vector2::direction () const {
}
}
+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 {
@@ -424,15 +480,19 @@ inline bool Vector2::isFinite() const {
inline bool Vector2::isZero() const {
- return (x == 0.0f) && (y == 0.0f);
+ return G3D::fuzzyEq(fabsf(x) + fabsf(y), 0.0f);
}
inline bool Vector2::isUnit() const {
- return squaredLength() == 1.0f;
+ 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 <>
diff --git a/dep/g3dlite/include/G3D/Vector2int16.h b/dep/g3dlite/include/G3D/Vector2int16.h
index ba72266d75a..d24662b18b9 100644
--- a/dep/g3dlite/include/G3D/Vector2int16.h
+++ b/dep/g3dlite/include/G3D/Vector2int16.h
@@ -4,14 +4,14 @@
@maintainer Morgan McGuire, matrix@brown.edu
@created 2003-08-09
- @edited 2004-01-03
+ @edited 2010-01-03
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef VECTOR2INT16_H
-#define VECTOR2INT16_H
+#ifndef Vector2int16_h
+#define Vector2int16_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
@@ -19,12 +19,13 @@
namespace G3D {
+class Any;
/**
\class Vector2int16
- A Vector2 that packs its fields into uint16s.
+ A Vector2 that packs its fields into G3D::int16 s.
*/
G3D_BEGIN_PACKED_CLASS(2)
-class Vector2int16 {
+Vector2int16 {
private:
// Hidden operators
bool operator<(const Vector2int16&) const;
@@ -38,8 +39,14 @@ public:
Vector2int16() : x(0), y(0) {}
Vector2int16(G3D::int16 _x, G3D::int16 _y) : x(_x), y(_y){}
- Vector2int16(const class Vector2& v);
- Vector2int16(class BinaryInput& bi);
+ 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);
@@ -63,6 +70,10 @@ public:
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);
}
@@ -73,6 +84,10 @@ public:
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);
@@ -118,6 +133,8 @@ public:
}
G3D_END_PACKED_CLASS(2)
+typedef Vector2int16 Point2int16;
+
}
template<> struct HashTrait<G3D::Vector2int16> {
diff --git a/dep/g3dlite/include/G3D/Vector2int32.h b/dep/g3dlite/include/G3D/Vector2int32.h
new file mode 100644
index 00000000000..fe161604c55
--- /dev/null
+++ b/dep/g3dlite/include/G3D/Vector2int32.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/Vector2unorm16.h b/dep/g3dlite/include/G3D/Vector2unorm16.h
new file mode 100644
index 00000000000..06902612a57
--- /dev/null
+++ b/dep/g3dlite/include/G3D/Vector2unorm16.h
@@ -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
diff --git a/dep/g3dlite/include/G3D/Vector3.h b/dep/g3dlite/include/G3D/Vector3.h
index b4e684b92e5..ef1e39d8211 100644
--- a/dep/g3dlite/include/G3D/Vector3.h
+++ b/dep/g3dlite/include/G3D/Vector3.h
@@ -1,13 +1,14 @@
/**
- @file Vector3.h
+ \file Vector3.h
3D vector class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2009-11-01
- Copyright 2000-2009, Morgan McGuire.
+ \created 2001-06-02
+ \edited 2010-12-25
+
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -72,29 +73,37 @@ public:
/** Initializes to zero */
Vector3();
- /** \param any Must either Vector3(#, #, #) or Vector3 {x = #, y = #, z = #}*/
- Vector3(const Any& any);
+ /**
+ \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. */
- operator Any() const;
+ 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(const class Vector2& v, float _z);
explicit Vector3(float coordinate[3]);
explicit Vector3(double coordinate[3]);
Vector3(const class Vector3int16& v);
- explicit Vector3(class TextInput& t);
+ explicit Vector3(class TextInput& t);
explicit Vector3(const class Color3& c);
- /** Format is three float32's */
+ /** Format is three float32's */
void serialize(class BinaryOutput& b) const;
void deserialize(class BinaryInput& b);
- /** Format is "(%f, %f, %f)" */
+ /** Format is "(%f, %f, %f)" */
void serialize(class TextOutput& t) const;
void deserialize(class TextInput& t);
@@ -106,6 +115,10 @@ public:
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};
/**
@@ -116,6 +129,7 @@ public:
// 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;
@@ -125,11 +139,18 @@ public:
/** 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;
@@ -153,12 +174,18 @@ public:
Vector3& __fastcall operator/= (const Vector3& v);
/** Same as magnitude */
- float length() const;
+ 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));
+ }
/**
- The result is a nan vector if the length is almost zero.
+ Returns a unit-length version of this vector.
+ Returns nan if length is almost zero.
*/
Vector3 direction() const;
@@ -265,11 +292,9 @@ public:
float squaredLength() const;
float squaredMagnitude () const;
-
+
float __fastcall dot(const Vector3& rkVector) const;
- float unitize(float tolerance = 1e-06);
-
/** Cross product. Note that two cross products in a row
can be computed more cheaply: v1 x (v2 x v3) = (v1 dot v3) v2 - (v1 dot v2) v3.
*/
@@ -315,6 +340,17 @@ public:
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
*/
@@ -347,6 +383,8 @@ public:
*/
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
@@ -370,14 +408,6 @@ public:
*/
static Vector3 hemiRandom(const Vector3& normal, Random& r = Random::common());
- /** Input W must be initialize to a nonzero vector, output is {U,V,W}
- an orthonormal basis. A hint is provided about whether or not W
- is already unit length.
- @deprecated Use getTangents
- */
- static void generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
- Vector3& rkW, bool bUnitLengthW = true);
-
inline float sum() const {
return x + y + z;
}
@@ -549,6 +579,8 @@ public:
static Vector3& ignore();
};
+
+
inline G3D::Vector3 operator*(float s, const G3D::Vector3& v) {
return v * s;
}
@@ -750,8 +782,7 @@ inline Vector3 Vector3::cross (const Vector3& rkVector) const {
inline Vector3 Vector3::unitCross (const Vector3& rkVector) const {
Vector3 kCross(y*rkVector.z - z*rkVector.y, z*rkVector.x - x*rkVector.z,
x*rkVector.y - y*rkVector.x);
- kCross.unitize();
- return kCross;
+ return kCross.direction();
}
//----------------------------------------------------------------------------
@@ -766,7 +797,7 @@ inline Vector3 Vector3::max(const Vector3 &v) const {
//----------------------------------------------------------------------------
inline bool Vector3::isZero() const {
- return G3D::fuzzyEq(squaredMagnitude(), 0.0f);
+ return G3D::fuzzyEq(fabsf(x) + fabsf(y) + fabsf(z), 0.0f);
}
//----------------------------------------------------------------------------
@@ -775,6 +806,22 @@ 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
diff --git a/dep/g3dlite/include/G3D/Vector3int16.h b/dep/g3dlite/include/G3D/Vector3int16.h
index 6043aea9f61..2cf4e5f1338 100644
--- a/dep/g3dlite/include/G3D/Vector3int16.h
+++ b/dep/g3dlite/include/G3D/Vector3int16.h
@@ -1,16 +1,17 @@
/**
- @file Vector3int16.h
+ \file G3D/Vector3int16.h
- @maintainer Morgan McGuire, matrix@brown.edu
+ \maintainer Morgan McGuire, matrix@brown.edu
- @created 2003-04-07
- @edited 2003-06-24
- Copyright 2000-2004, Morgan McGuire.
+ \created 2003-04-07
+ \edited 2011-06-24
+
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef VECTOR3INT16_H
-#define VECTOR3INT16_H
+#ifndef G3D_Vector3int16_h
+#define G3D_Vector3int16_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
@@ -19,6 +20,7 @@
#ifdef _MSC_VER
// Turn off "conditional expression is constant" warning; MSVC generates this
// for debug assertions in inlined methods.
+#pragma warning (push)
#pragma warning (disable : 4127)
#endif
@@ -30,7 +32,7 @@ namespace G3D {
A Vector3 that packs its fields into uint16s.
*/
G3D_BEGIN_PACKED_CLASS(2)
-class Vector3int16 {
+Vector3int16 {
private:
// Hidden operators
bool operator<(const Vector3int16&) const;
@@ -45,8 +47,8 @@ public:
Vector3int16() : x(0), y(0), z(0) {}
Vector3int16(G3D::int16 _x, G3D::int16 _y, G3D::int16 _z) : x(_x), y(_y), z(_z) {}
- Vector3int16(const class Vector3& v);
- Vector3int16(class BinaryInput& bi);
+ explicit Vector3int16(const class Vector3& v);
+ explicit Vector3int16(class BinaryInput& bi);
void serialize(class BinaryOutput& bo) const;
void deserialize(class BinaryInput& bi);
@@ -98,6 +100,9 @@ public:
return *this;
}
+ static Vector3int16 floor(const Vector3& v);
+ static Vector3int16 ceil(const Vector3& v);
+
inline bool operator== (const Vector3int16& rkVector) const {
return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
}
@@ -106,6 +111,10 @@ public:
return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
}
+ int dot(const Vector3int16& v) const {
+ return x * v.x + y * v.y + z * v.z;
+ }
+
Vector3int16 max(const Vector3int16& v) const {
return Vector3int16(std::max(x, v.x), std::max(y, v.y), std::max(z, v.z));
}
@@ -115,13 +124,49 @@ public:
}
std::string toString() const;
+
+
+ Vector3int16 operator-() const {
+ return Vector3int16(-x, -y, -z);
+ }
+
+ Vector3int16 operator<<(int i) const {
+ return Vector3int16(x << i, y << i, z << i);
+ }
+
+ Vector3int16 operator>>(int i) const {
+ return Vector3int16(x >> i, y >> i, z >> i);
+ }
+
+ Vector3int16 operator>>(const Vector3int16& v) const {
+ return Vector3int16(x >> v.x, y >> v.y, z >> v.z);
+ }
+
+ Vector3int16 operator<<(const Vector3int16& v) const {
+ return Vector3int16(x << v.x, y << v.y, z << v.z);
+ }
+
+ Vector3int16 operator&(int16 i) const {
+ return Vector3int16(x & i, y & i, z & i);
+ }
+
+ Vector3int16 operator&(const Vector3int16& v) const {
+ return Vector3int16(x & v.x, y & v.y, z & v.z);
+ }
}
G3D_END_PACKED_CLASS(2)
-}
+typedef Vector3int16 Point3int16;
+
+} // namespace G3D
template <> struct HashTrait<G3D::Vector3int16> {
static size_t hashCode(const G3D::Vector3int16& key) { return static_cast<size_t>(key.x + ((int)key.y << 5) + ((int)key.z << 10)); }
};
+
+#ifdef G3D_WINDOWS
+#pragma warning( pop )
+#endif
+
#endif
diff --git a/dep/g3dlite/include/G3D/Vector3int32.h b/dep/g3dlite/include/G3D/Vector3int32.h
index c1a6b21e100..c682278667d 100644
--- a/dep/g3dlite/include/G3D/Vector3int32.h
+++ b/dep/g3dlite/include/G3D/Vector3int32.h
@@ -1,29 +1,32 @@
/**
- @file Vector3int32.h
+ @file G3D/Vector3int32.h
@maintainer Morgan McGuire, matrix@brown.edu
@created 2008-07-01
- @edited 2008-07-01
- Copyright 2000-2009, Morgan McGuire.
+ @edited 2011-01-01
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef VECTOR3INT32_H
-#define VECTOR3INT32_H
+#ifndef G3D_Vector3int32_h
+#define G3D_Vector3int32_h
#include "G3D/platform.h"
#include "G3D/g3dmath.h"
#include "G3D/HashTrait.h"
+#include "G3D/Crypto.h"
namespace G3D {
+ class Any;
+
/**
\ Vector3int32
A Vector3 that packs its fields into uint32s.
*/
G3D_BEGIN_PACKED_CLASS(4)
-class Vector3int32 {
+Vector3int32 {
private:
// Hidden operators
bool operator<(const Vector3int32&) const;
@@ -38,9 +41,21 @@ public:
Vector3int32() : x(0), y(0), z(0) {}
Vector3int32(int _x, int _y, int _z) : x(_x), y(_y), z(_z) {}
+ Vector3int32(const class Vector2int32& v, int _z);
+ Vector3int32(const class Vector2int16& v, int _z);
Vector3int32(const class Vector3int16& v);
- Vector3int32(const class Vector3& v);
- Vector3int32(class BinaryInput& bi);
+ Vector3int32(const Any& any);
+ Any toAny() const;
+
+ /** Rounds to the nearest int */
+ explicit Vector3int32(const class Vector3& v);
+ explicit Vector3int32(class BinaryInput& bi);
+
+ static Vector3int32 truncate(const class Vector3& v);
+
+ bool nonZero() const {
+ return (x != 0) || (y != 0) || (z != 0);
+ }
void serialize(class BinaryOutput& bo) const;
void deserialize(class BinaryInput& bi);
@@ -71,32 +86,42 @@ public:
return Vector3int32(x * s, y * s, z * s);
}
- inline Vector3int32& operator+=(const Vector3int32& other) {
+ /** Integer division */
+ inline Vector3int32 operator/(const Vector3int32& other) const {
+ return Vector3int32(x / other.x, y / other.y, z / other.z);
+ }
+
+ /** Integer division */
+ inline Vector3int32 operator/(const int s) const {
+ return Vector3int32(x / s, y / s, z / s);
+ }
+
+ Vector3int32& operator+=(const Vector3int32& other) {
x += other.x;
y += other.y;
z += other.z;
return *this;
}
- inline Vector3int32& operator-=(const Vector3int32& other) {
+ Vector3int32& operator-=(const Vector3int32& other) {
x -= other.x;
y -= other.y;
z -= other.z;
return *this;
}
- inline Vector3int32& operator*=(const Vector3int32& other) {
+ Vector3int32& operator*=(const Vector3int32& other) {
x *= other.x;
y *= other.y;
z *= other.z;
return *this;
}
- inline bool operator== (const Vector3int32& rkVector) const {
+ bool operator== (const Vector3int32& rkVector) const {
return ( x == rkVector.x && y == rkVector.y && z == rkVector.z );
}
- inline bool operator!= (const Vector3int32& rkVector) const {
+ bool operator!= (const Vector3int32& rkVector) const {
return ( x != rkVector.x || y != rkVector.y || z != rkVector.z );
}
@@ -108,20 +133,64 @@ public:
return Vector3int32(iMin(x, v.x), iMin(y, v.y), iMin(z, v.z));
}
+ Vector3int32 operator-() const {
+ return Vector3int32(-x, -y, -z);
+ }
+
std::string toString() const;
+
+ Vector3int32 operator<<(int i) const {
+ return Vector3int32(x << i, y << i, z << i);
+ }
+
+ Vector3int32 operator>>(int i) const {
+ return Vector3int32(x >> i, y >> i, z >> i);
+ }
+
+ Vector3int32 operator>>(const Vector3int32& v) const {
+ return Vector3int32(x >> v.x, y >> v.y, z >> v.z);
+ }
+
+ Vector3int32 operator<<(const Vector3int32& v) const {
+ return Vector3int32(x << v.x, y << v.y, z << v.z);
+ }
+
+ Vector3int32 operator&(int16 i) const {
+ return Vector3int32(x & i, y & i, z & i);
+ }
+
+ // 2-char swizzles
+
+ Vector2int32 xx() const;
+ Vector2int32 yx() const;
+ Vector2int32 zx() const;
+ Vector2int32 xy() const;
+ Vector2int32 yy() const;
+ Vector2int32 zy() const;
+ Vector2int32 xz() const;
+ Vector2int32 yz() const;
+ Vector2int32 zz() const;
}
G3D_END_PACKED_CLASS(4)
-}
+typedef Vector3int32 Point3int32;
+
+Vector3int32 iFloor(const Vector3&);
+
+} // namespace G3D
template <> struct HashTrait<G3D::Vector3int32> {
static size_t hashCode(const G3D::Vector3int32& key) {
+ return G3D::superFastHash(&key, sizeof(key));
+ //return G3D::Crypto::crc32(&key, sizeof(key));
+ /*
// Mask for the top bit of a uint32
const G3D::uint32 top = (1UL << 31);
// Mask for the bottom 10 bits of a uint32
const G3D::uint32 bot = 0x000003FF;
return static_cast<size_t>(((key.x & top) | ((key.y & top) >> 1) | ((key.z & top) >> 2)) |
(((key.x & bot) << 19) ^ ((key.y & bot) << 10) ^ (key.z & bot)));
+ */
}
};
diff --git a/dep/g3dlite/include/G3D/Vector4.h b/dep/g3dlite/include/G3D/Vector4.h
index 5e511451f86..24521efc93c 100644
--- a/dep/g3dlite/include/G3D/Vector4.h
+++ b/dep/g3dlite/include/G3D/Vector4.h
@@ -47,10 +47,11 @@ private:
public:
/** \param any Must either Vector4(#, #, #, #) or Vector3 {x = #, y = #, z = #, w =#}*/
- Vector4(const Any& any);
+ explicit Vector4(const Any& any);
+ Vector4& operator=(const Any& a);
/** Converts the Vector4 to an Any. */
- operator Any() const;
+ Any toAny() const;
// construction
Vector4();
@@ -698,7 +699,11 @@ inline float Vector4::squaredLength() const {
return x * x + y * y + z * z + w * w;
}
-}
+
+void serialize(const Vector4& v, class BinaryOutput& b);
+void deserialize(Vector4& v, class BinaryInput& b);
+
+} // G3D
template <> struct HashTrait<G3D::Vector4> {
static size_t hashCode(const G3D::Vector4& key) { return key.hashCode(); }
diff --git a/dep/g3dlite/include/G3D/Vector4int8.h b/dep/g3dlite/include/G3D/Vector4int8.h
index 544b693e8b3..14fe7fe0cbb 100644
--- a/dep/g3dlite/include/G3D/Vector4int8.h
+++ b/dep/g3dlite/include/G3D/Vector4int8.h
@@ -51,14 +51,14 @@ public:
inline Vector4int8() : x(0), y(0), z(0), w(0) {}
/** Multiplies the source by 127 and clamps to (-128, 127) when converting */
- Vector4int8(const Vector4& source);
+ explicit Vector4int8(const Vector4& source);
/** Multiplies the source by 127 and clamps to (-128, 127) when converting */
- Vector4int8(const Vector3& source, int8 w);
+ explicit Vector4int8(const Vector3& source, int8 w);
inline Vector4int8(int8 x, int8 y, int8 z, int8 w) : x(x), y(y), z(z), w(w) {}
- Vector4int8(class BinaryInput& b);
+ explicit Vector4int8(class BinaryInput& b);
void serialize(class BinaryOutput& b) const;
void deserialize(class BinaryInput& b);
diff --git a/dep/g3dlite/include/G3D/WeakCache.h b/dep/g3dlite/include/G3D/WeakCache.h
index f9fdc4bbd5b..b2f43818ba3 100644
--- a/dep/g3dlite/include/G3D/WeakCache.h
+++ b/dep/g3dlite/include/G3D/WeakCache.h
@@ -1,16 +1,16 @@
/**
- @file WeakCache.h
+ \file G3D/WeakCache.h
- @maintainer Morgan McGuire, graphics3d.com
+ \maintainer Morgan McGuire, graphics3d.com
- @created 2007-05-16
- @edited 2007-05-16
+ \created 2007-05-16
+ \edited 2012-01-02
- Copyright 2000-2007, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_WEAKCACHE_H
-#define G3D_WEAKCACHE_H
+#ifndef G3D_WeakCache_h
+#define G3D_WeakCache_h
#include "G3D/ReferenceCount.h"
#include "G3D/Table.h"
@@ -31,10 +31,10 @@ namespace G3D {
Example:
<pre>
- WeakCache<std::string, TextureRef> textureCache;
+ WeakCache<std::string, shared_ptr<Texture>> textureCache;
- TextureRef loadTexture(std::string s) {
- TextureRef t = textureCache[s];
+ shared_ptr<Texture> loadTexture(std::string s) {
+ shared_ptr<Texture> t = textureCache[s];
if (t.isNull()) {
t = Texture::fromFile(s);
@@ -49,7 +49,7 @@ namespace G3D {
*/
template<class Key, class ValueRef>
class WeakCache {
- typedef WeakReferenceCountedPointer<typename ValueRef::element_type> ValueWeakRef;
+ typedef weak_ptr<typename ValueRef::element_type> ValueWeakRef;
private:
@@ -62,46 +62,32 @@ public:
ValueRef operator[](const Key& k) {
if (table.containsKey(k)) {
ValueWeakRef w = table[k];
- ValueRef s = w.createStrongPtr();
- if (s.isNull()) {
+ ValueRef s = w.lock();
+ if (! s) {
// This object has been collected; clean out its key
table.remove(k);
}
return s;
} else {
- return NULL;
+ return ValueRef();
}
}
- void set(const Key& k, ValueRef v) {
- table.set(k, v);
- }
- /** Removes k from the cache or does nothing if it is not currently in the cache.*/
- void remove(const Key& k) {
- if (table.containsKey(k)) {
- table.remove(k);
+
+ void getValues(Array<ValueRef>& values) {
+ Array<Key> keys;
+ table.getKeys(keys);
+ for (int i = 0; i < keys.size(); ++i) {
+ ValueRef value = (*this)[keys[i]];
+ if(notNull(value)) {
+ values.append(value);
+ }
}
}
-};
-
-#if 0 // To turn off all WeakCaching
-template<class Key, class ValueRef>
-class WeakCache {
-private:
-
- Table<Key, ValueRef> table;
-public:
- /**
- Returns NULL if the object is not in the cache
- */
- ValueRef operator[](const Key& k) {
- if (table.containsKey(k)) {
- return table[k];
- } else {
- return NULL;
- }
+ void clear() {
+ table.clear();
}
void set(const Key& k, ValueRef v) {
@@ -115,7 +101,6 @@ public:
}
}
};
-#endif
}
#endif
diff --git a/dep/g3dlite/include/G3D/Welder.h b/dep/g3dlite/include/G3D/Welder.h
index 2c2554da7b6..8ab65cfa44a 100644
--- a/dep/g3dlite/include/G3D/Welder.h
+++ b/dep/g3dlite/include/G3D/Welder.h
@@ -22,30 +22,38 @@ public:
/** Surfaces with normals that are within this angle of each
other are considered to be curved. Default value is toRadians(70.0f).*/
float normalSmoothingAngle;
- float vertexWeldRadius;
- float textureWeldRadius;
- float normalWeldRadius;
+
+ /** Default value is 0 */
+ float vertexWeldRadius;
+
+ float textureWeldRadius;
+
+ float normalWeldRadius;
inline Settings(float normalSmoothAngle = toRadians(70.0f)) :
normalSmoothingAngle(normalSmoothAngle),
- vertexWeldRadius(0.0001f),
+ vertexWeldRadius(0.001f),
textureWeldRadius(0.0001f),
normalWeldRadius(0.01f) {}
Settings(const Any& any);
- operator Any() const;
+
+ Any toAny() const;
+
+ void serialize(class BinaryOutput& b) const;
+
+ void deserialize(class BinaryInput& b);
};
/**
- Mutates geometry, texCoord, and indexArray so that the output has collocated vertices collapsed (welded).
+ Mutates geometry, texCoord, and indexArray so that the output has
+ collocated vertices collapsed (welded).
@param vertices Input and output
@param textureCoords Input and output
@param normals Output only
@param indices Input and output. This is an array of trilist indices.
- @param oldToNewIndex Output argument
- @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70)
*/
static void weld(
Array<Vector3>& vertices,
@@ -61,8 +69,6 @@ public:
@param textureCoords Input and output
@param normals Output only
@param indices Input and output. This is an array of trilist indices.
- @param oldToNewIndex Output argument
- @param normalSmoothingAngle Varies from 0 (flat shading) to toRadians(180) for extremely smooth shading. Default is toRadians(70)
*/
inline static void weld(
Array<Vector3>& vertices,
diff --git a/dep/g3dlite/include/G3D/WrapMode.h b/dep/g3dlite/include/G3D/WrapMode.h
index 25a2fb47256..e71d6dfa621 100644
--- a/dep/g3dlite/include/G3D/WrapMode.h
+++ b/dep/g3dlite/include/G3D/WrapMode.h
@@ -1,12 +1,12 @@
/**
- @file WrapMode.h
+ \file G3D/WrapMode.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-04-17
- @edited 2010-04-17
+ \created 2007-04-17
+ \edited 2010-04-17
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -15,7 +15,6 @@
#include "G3D/platform.h"
#include "G3D/enumclass.h"
-#include "G3D/Any.h"
#ifdef IGNORE
# undef IGNORE
@@ -62,9 +61,7 @@ public:
ZERO,
IGNORE,
ERROR
- };
-
-private:
+ } value;
static const char* toString(int i, Value& v) {
static const char* str[] = {"CLAMP", "TILE", "ZERO", "IGNORE", "ERROR", NULL};
@@ -76,14 +73,11 @@ private:
return s;
}
- Value value;
-
-public:
G3D_DECLARE_ENUM_CLASS_METHODS(WrapMode);
-
};
+
} // namespace G3D
G3D_DECLARE_ENUM_CLASS_HASHCODE(G3D::WrapMode);
diff --git a/dep/g3dlite/include/G3D/XML.h b/dep/g3dlite/include/G3D/XML.h
index 9ff98f9d171..82816d20f6a 100644
--- a/dep/g3dlite/include/G3D/XML.h
+++ b/dep/g3dlite/include/G3D/XML.h
@@ -7,7 +7,7 @@
@created 2010-02-11
@edited 2010-02-24
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -52,6 +52,7 @@ end with "-->" e.g.,
\sa G3D::Any, http://www.grinninglizard.com/tinyxml/
+\htmlonly
<pre>
<foo key0="value0" key1="value1">
child0 ...
@@ -59,6 +60,7 @@ end with "-->" e.g.,
child2 ...
</foo>
</pre>
+\endhtmlonly
*/
class XML {
public:
@@ -117,7 +119,7 @@ public:
return m_attribute;
}
- const Array<XML> childArray() const {
+ const Array<XML>& childArray() const {
return m_child;
}
@@ -127,7 +129,7 @@ public:
}
/** Attribute table size; zero for a TAG */
- int numAttributes() const {
+ size_t numAttributes() const {
return m_attribute.size();
}
@@ -142,7 +144,7 @@ public:
return m_attribute[k];
}
- const bool containsAttribute(const std::string& k) const {
+ bool containsAttribute(const std::string& k) const {
return m_attribute.containsKey(k);
}
diff --git a/dep/g3dlite/include/G3D/constants.h b/dep/g3dlite/include/G3D/constants.h
index 4121f744e17..edecf10e19e 100644
--- a/dep/g3dlite/include/G3D/constants.h
+++ b/dep/g3dlite/include/G3D/constants.h
@@ -26,20 +26,13 @@ public:
TRIANGLE_STRIP = 0x0005,
TRIANGLE_FAN = 0x0006,
QUADS = 0x0007,
- QUAD_STRIP = 0x0008
+ QUAD_STRIP = 0x0008,
+ PATCHES = 0x000E
};
private:
- static const char* toString(int i, Value& v) {
- static const char* str[] = {"POINTS", "LINES", "LINE_STRIP", "TRIANGLES", "TRIANGLE_FAN", "QUADS", "QUAD_STRIP", NULL};
- static const Value val[] = {POINTS, LINES, LINE_STRIP, TRIANGLES, TRIANGLE_FAN, QUADS, QUAD_STRIP};
- const char* s = str[i];
- if (s) {
- v = val[i];
- }
- return s;
- }
+ static const char* toString(int i, Value& v);
Value value;
@@ -49,7 +42,7 @@ public:
};
-/** Values for SuperSurface::GPUGeom::refractionHint. */
+/** Values for UniversalSurface::GPUGeom::refractionHint. */
class RefractionQuality {
public:
enum Value {
@@ -77,15 +70,7 @@ public:
private:
- static const char* toString(int i, Value& v) {
- static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST", NULL};
- static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_FLAT, DYNAMIC_FLAT_MULTILAYER, DYNAMIC_ENV, BEST};
- const char* s = str[i];
- if (s) {
- v = val[i];
- }
- return s;
- }
+ static const char* toString(int i, Value& v);
Value value;
@@ -95,7 +80,7 @@ public:
};
-/** Values for SuperSurface::GPUGeom::mirrorHint. */
+/** Values for UniversalSurface::GPUGeom::mirrorHint. */
class MirrorQuality {
public:
@@ -119,15 +104,7 @@ public:
private:
- static const char* toString(int i, Value& v) {
- static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST", NULL};
- static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_PLANAR, DYNAMIC_ENV, BEST};
- const char* s = str[i];
- if (s) {
- v = val[i];
- }
- return s;
- }
+ static const char* toString(int i, Value& v);
Value value;
diff --git a/dep/g3dlite/include/G3D/debug.h b/dep/g3dlite/include/G3D/debug.h
index a7697fe9c01..4f34e5b3b62 100644
--- a/dep/g3dlite/include/G3D/debug.h
+++ b/dep/g3dlite/include/G3D/debug.h
@@ -1,17 +1,17 @@
/**
- @file debug.h
+ \file debug.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-08-26
- @edited 2006-02-16
+ \created 2001-08-26
+ \edited 2008-08-16
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2006, Morgan McGuire.
All rights reserved.
*/
-#ifndef G3D_DEBUG_H
-#define G3D_DEBUG_H
+#ifndef G3D_debug_h
+#define G3D_debug_h
#include "G3D/platform.h"
#ifdef _MSC_VER
@@ -38,7 +38,9 @@ namespace G3D {
inline bool isValidHeapPointer(const void* x) {
#ifdef _MSC_VER
return
- (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee);
+ (x != NULL) &&
+ (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee) &&
+ (x != (void*)0xcdcdcdcd) && (x != (void*)0xabababab) && (x != (void*)0xfdfdfdfd);
#else
return x != NULL;
#endif
@@ -51,7 +53,9 @@ inline bool isValidHeapPointer(const void* x) {
*/
inline bool isValidPointer(const void* x) {
#ifdef _MSC_VER
- return x != ((void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee);
+ return (x != NULL) &&
+ (x != (void*)0xcccccccc) && (x != (void*)0xdeadbeef) && (x != (void*)0xfeeefeee) &&
+ (x != (void*)0xcdcdcdcd) && (x != (void*)0xabababab) && (x != (void*)0xfdfdfdfd);
#else
return x != NULL;
#endif
diff --git a/dep/g3dlite/include/G3D/enumclass.h b/dep/g3dlite/include/G3D/enumclass.h
index 2874a630ad9..8e0c221f8fd 100644
--- a/dep/g3dlite/include/G3D/enumclass.h
+++ b/dep/g3dlite/include/G3D/enumclass.h
@@ -1,30 +1,39 @@
/**
- @file G3D/enumclass.h
+ \file G3D/enumclass.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-27
- @edited 2007-07-20
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2007-01-27
+ \edited 2013-04-09
*/
#ifndef G3D_enumclass_h
#define G3D_enumclass_h
+#include "G3D/platform.h"
#include "G3D/HashTrait.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/TextOutput.h"
+#include "G3D/Any.h"
+
+namespace G3D {
+ namespace _internal {
+ const char** smartEnumParseNames(const char* enumValList);
+ }
+}
/**
\def G3D_DECLARE_ENUM_CLASS_METHODS
\brief Creates a series of methods that turn a class into a scoped enumeration.
- Uses the "Intelligent Enum" design pattern
- http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/
-
- Enum classes are initialized to their zero value by default.
-
- You must implement the following method before calling G3D_DECLARE_ENUM_CLASS_METHODS, as either:
+ Example of use:
- <pre>
+ \code
+ class Resource {
+ public:
+ enum Value {FUEL, FOOD, WATER} value;
+
+ // i is the position the enum value in Value (not the enum value itself)
static const char* toString(int i, Value& v) {
static const char* str[] = {"FUEL", "FOOD", "WATER", NULL}; // Whatever your enum values are
static const Value val[] = {FUEL, FOOD, WATER}; // Whatever your enum values are
@@ -34,29 +43,42 @@
}
return s;
}
- </pre>
- See GLG3D/GKey.h for an example.
+ G3D_DECLARE_ENUM_CLASS_METHODS(Resource);
+ };
+ G3D_DECLARE_ENUM_CLASS_HASHCODE(Resource);
+ \endcode
+
+ Extends the "Intelligent Enum" design pattern
+ http://www.codeguru.com/cpp/cpp/cpp_mfc/article.php/c4001/
+
+ Enum classes are initialized to their zero value by default.
+
+ See GLG3D/GKey.h and G3D/WrapMode for an example.
\sa G3D_DECLARE_ENUM_CLASS_HASHCODE
*/
#define G3D_DECLARE_ENUM_CLASS_METHODS(Classname)\
private: \
void fromString(const std::string& x) {\
- Value v;\
+ Value v = (Value)0;\
const char* s;\
int i = 0;\
\
do {\
s = toString(i, v);\
+ if (s == NULL) { return; /** Needed to get correct compilation on gcc */ } \
if (x == s) {\
value = v;\
return;\
}\
++i;\
- } while (s);\
+ } while (true);\
}\
\
public:\
+ static const char* classname() {\
+ return #Classname;\
+ }\
\
const char* toString() const {\
const char* s;\
@@ -69,22 +91,21 @@ public:\
}\
++i;\
}\
- return NULL;\
}\
\
explicit Classname(const std::string& x) : value((Value)0) {\
fromString(x);\
}\
\
- Classname(const Any& a) : value((Value)0) {\
+ explicit Classname(const G3D::Any& a) : value((Value)0) { \
fromString(a.string());\
}\
\
- operator Any() const {\
- return Any(toString());\
+ G3D::Any toAny() const { \
+ return G3D::Any(toString()); \
}\
\
- Classname(char v) : value((Value)v) {}\
+ explicit Classname(char v) : value((Value)v) {}\
\
Classname() : value((Value)0) {}\
\
@@ -92,15 +113,15 @@ public:\
\
explicit Classname(int v) : value((Value)v) {}\
\
- /** Support cast back to the Value type, which is needed to allow implicit assignment inside unions. */\
- /*inline operator Value() const {
- return value;
- }*/\
-\
operator int() const {\
return (int)value;\
}\
\
+ Classname& operator=(const Any& a) {\
+ value = Classname(a).value;\
+ return *this;\
+ }\
+\
bool operator== (const Classname other) const {\
return value == other.value;\
}\
@@ -181,15 +202,16 @@ public:\
return (unsigned int)value;\
}\
\
- void serialize(BinaryOutput& b) const {\
+ void serialize(G3D::BinaryOutput& b) const { \
b.writeInt32(value);\
}\
\
- void deserialize(BinaryInput& b) {\
+ void deserialize(G3D::BinaryInput& b) { \
value = (Value)b.readInt32();\
}
/** \def G3D_DECLARE_ENUM_CLASS_HASHCODE
+ Must be used at top level (i.e., not inside a class or namespace), with a fully qualified class name.
*/
#define G3D_DECLARE_ENUM_CLASS_HASHCODE(Classname)\
template <> struct HashTrait<Classname::Value> \
@@ -202,4 +224,108 @@ template <> struct HashTrait<Classname>
static size_t hashCode(Classname key) { return static_cast<size_t>(key.hashCode()); } \
};
+/**
+\def G3D_DECLARE_ENUM_CLASS
+
+\code
+// Arguments may not have initializer expressions. Arguments may contain comments.
+// Namespaces aren't *required*, this example just shows how to use them.
+namespace Foo {
+ G3D_DECLARE_ENUM_CLASS(Day, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY);
+}
+G3D_DECLARE_ENUM_CLASS_HASHCODE(Foo::Day);
+...
+
+using namespace Foo;
+// Example use of the smart enum
+Day d = Day::TUESDAY;
+Day d2("SATURDAY");
+Any a(d);
+d = a;
+printf("%s = %d\n", d.toString(), d.value);
+\endcode
+
+\sa G3D_DECLARE_ENUM_CLASS_METHODS, G3D_DECLARE_ENUM_CLASS_HASHCODE, G3D::enumToJavaScriptDeclaration, G3D_BEGIN_ENUM_CLASS_DECLARATION
+*/
+#define G3D_DECLARE_ENUM_CLASS(ClassName, ...)\
+ G3D_BEGIN_ENUM_CLASS_DECLARATION(ClassName, __VA_ARGS__);\
+ G3D_END_ENUM_CLASS_DECLARATION();
+
+/** \def G3D_BEGIN_ENUM_CLASS_DECLARATION
+
+\code
+G3D_BEGIN_ENUM_CLASS_DECLARATION(Day, SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY);
+ // Put extra methods here, e.g.,
+ Value nextValue() { ... }
+G3D_END_ENUM_CLASS_DECLARATION();
+}
+G3D_DECLARE_ENUM_CLASS_HASHCODE(Foo::Day);
+
+\endcode
+ \sa G3D_DECLARE_ENUM_CLASS, G3D_END_ENUM_CLASS_DECLARATION
+*/
+#define G3D_BEGIN_ENUM_CLASS_DECLARATION(ClassName, ...)\
+class ClassName {\
+public:\
+ enum Value {\
+ __VA_ARGS__\
+ } value;\
+\
+ /* The static variables here may be duplicated in different shared object binaries (DLLs), but that's ok--we only depend on their values, not their uniqueness. See also http://stackoverflow.com/questions/11962918/local-static-variable-is-instantiated-multiple-times-why */\
+ static const char* toString(int i, Value& v) {\
+ static const char** str = G3D::_internal::smartEnumParseNames(#__VA_ARGS__);\
+ static const Value val[] = {__VA_ARGS__};\
+ const char* s = str[i];\
+ if (s) { v = val[i]; }\
+ return s;\
+ }\
+\
+ G3D_DECLARE_ENUM_CLASS_METHODS(ClassName);
+
+/** \def G3D_END_ENUM_CLASS_DECLARATION
+ \sa G3D_BEGIN_ENUM_CLASS_DECLARATION */
+#define G3D_END_ENUM_CLASS_DECLARATION() }
+
+
+namespace G3D {
+
+/**
+ \brief Generates JavaScript source code defining an enum equivalent to
+ EnumClass.
+
+ \code
+ TextOutput t("WrapMode.js");
+ enumToJavaScriptDeclaration<WrapMode, WrapMode::Value>(t);
+ t.commit();
+ \endcode
+ */
+template<class EnumClass, class EnumClassValue>
+void enumToJavaScriptDeclaration(TextOutput& t) {
+ t.printf("/* BEGIN GENERATED CODE. The following was automatically generated by G3D::enumToJavaScriptDeclaration(). Do not edit it manually. */\n\n");
+ t.printf("var %s = (function (propList) {", EnumClass::classname()); t.writeNewline();
+ t.pushIndent(); {
+ t.printf("// Define immutable properties"); t.writeNewline();
+ t.printf("var en = {};"); t.writeNewline();
+ t.printf("for (var i = 0; i < propList.length; i += 2)"); t.writeNewline();
+ t.pushIndent(); {
+ t.printf("Object.defineProperty(en, propList[i], {enumerable: true, value: propList[i + 1]});"); t.writeNewline();
+ } t.popIndent();
+ t.printf("return en;");
+ t.writeNewline();
+ } t.popIndent();
+ t.printf("})([");
+ int i = 0;
+ EnumClassValue m;
+ const char* s = EnumClass::toString(i, m);
+ while (notNull(s)) {
+ t.printf("\"%s\", %d, ", s, int(m));
+ ++i;
+ s = EnumClass::toString(i, m);
+ }
+ // JavaScript allows a trailing comma
+ t.printf("]);"); t.writeNewline();
+ t.printf("/* END GENERATED CODE */"); t.writeNewline();
+}
+
+}
#endif
diff --git a/dep/g3dlite/include/G3D/fileutils.h b/dep/g3dlite/include/G3D/fileutils.h
index 89b41690206..7717d6f72fd 100644
--- a/dep/g3dlite/include/G3D/fileutils.h
+++ b/dep/g3dlite/include/G3D/fileutils.h
@@ -4,9 +4,9 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@author 2002-06-06
- @edited 2010-03-06
+ @edited 2011-03-06
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -20,42 +20,16 @@
#include "G3D/Set.h"
#include "G3D/g3dmath.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
// For chdir, mkdir, etc.
# include <direct.h>
#endif
namespace G3D {
-
- namespace _internal {
- extern Set<std::string> currentFilesUsed;
- }
-
-/** Returns all the files used by G3D and GLG3D during the current execution. */
-Array<std::string> filesUsed();
-
-std::string readWholeFile(
- const std::string& filename);
-
-
-/** Reads from a zip file and decompresses the desired contents
- into memory. Does not support recursive zip calls (i.e. a .zip
- stored within another .zip)
-
- @param file the path, of the format C:\\...\\something.zip\\...\\desiredfile.ext
- @param data a pointer to the memory where the file will be stored
- @param length the size of the file decompressed to memory */
-void zipRead(const std::string& file,
- void*& data,
- size_t& length);
-
-
-/** Closes the contents of a zip file that had been decompressed to
- memory. Must be called in tandem with zipRead() to avoid memory
- leaks.
-
- @param data the pointer to the decompressed file in memory */
-void zipClose(void* data);
+
+/** Returns the contents of a text file as a single string */
+std::string readWholeFile
+(const std::string& filename);
/**
@@ -88,8 +62,8 @@ FILE* createTempFile();
*/
bool zipfileExists
(const std::string& filename,
- std::string& outZipfile,
- std::string& outInternalFile);
+ std::string& outZipfile,
+ std::string& outInternalFile);
bool zipfileExists(const std::string& filename);
diff --git a/dep/g3dlite/include/G3D/g3dfnmatch.h b/dep/g3dlite/include/G3D/g3dfnmatch.h
index 464b3927eee..186b795654c 100644
--- a/dep/g3dlite/include/G3D/g3dfnmatch.h
+++ b/dep/g3dlite/include/G3D/g3dfnmatch.h
@@ -42,7 +42,7 @@
namespace G3D {
-#if defined(G3D_WIN32)
+#if defined(G3D_WINDOWS)
# if ! defined(FNM_NOMATCH)
# define FNM_NOMATCH 1 /* Match failed. */
diff --git a/dep/g3dlite/include/G3D/g3dmath.h b/dep/g3dlite/include/G3D/g3dmath.h
index 4be723ca30c..a32fdaf604d 100644
--- a/dep/g3dlite/include/G3D/g3dmath.h
+++ b/dep/g3dlite/include/G3D/g3dmath.h
@@ -7,9 +7,9 @@
@cite highestBit by Jukka Liimatta
@created 2001-06-02
- @edited 2009-04-07
+ @edited 2013-01-27
- Copyright 2000-2006, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -29,6 +29,7 @@
#include <float.h>
#include <limits>
#include <stdlib.h>
+#include <stdint.h>
#if defined(_MSC_VER) && (_MSC_VER < 1000)
// Visual Studio is missing inttypes.h
@@ -58,6 +59,16 @@
#undef min
#undef max
+/**
+\def G3D_DECLARE_SYMBOL(s)
+Defines SYMBOL_s as a static const std::string with the value s.
+Useful for avoiding heap allocation from C-string constants being
+converted at runtime.
+*/
+#define G3D_DECLARE_SYMBOL(s) \
+ static const std::string SYMBOL_##s = #s
+
+
namespace G3D {
#ifdef _MSC_VER
@@ -65,59 +76,61 @@ inline double __fastcall drand48() {
return ::rand() / double(RAND_MAX);
}
-#if !defined(_WIN64)
-
-/**
- Win32 implementation of the C99 fast rounding routines.
+# ifdef _M_IX86
+ // 32-bit
+ /**
+ Win32 implementation of the C99 fast rounding routines.
- @cite routines are
- Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
+ @cite routines are
+ Copyright (C) 2001 Erik de Castro Lopo <erikd AT mega-nerd DOT com>
- Permission to use, copy, modify, distribute, and sell this file for any
- purpose is hereby granted without fee, provided that the above copyright
- and this permission notice appear in all copies. No representations are
- made about the suitability of this software for any purpose. It is
- provided "as is" without express or implied warranty.
-*/
+ Permission to use, copy, modify, distribute, and sell this file for any
+ purpose is hereby granted without fee, provided that the above copyright
+ and this permission notice appear in all copies. No representations are
+ made about the suitability of this software for any purpose. It is
+ provided "as is" without express or implied warranty.
+ */
-__inline long int lrint (double flt) {
- int intgr;
- _asm {
- fld flt
- fistp intgr
- };
+ __inline long int lrint (double flt) {
+ int intgr;
- return intgr;
-}
+ _asm {
+ fld flt
+ fistp intgr
+ };
-__inline long int lrintf(float flt) {
- int intgr;
+ return intgr;
+ }
- _asm {
- fld flt
- fistp intgr
- };
+ __inline long int lrintf(float flt) {
+ int intgr;
- return intgr;
-}
+ _asm {
+ fld flt
+ fistp intgr
+ };
-#else
+ return intgr;
+ }
+# else
+ // 64-bit
- __inline long int lrint (double flt) {
- return (long int)floor(flt+0.5f);
+ __inline long int lrintf(float flt) {
+ return (long int)(flt + 0.5f);
}
- __inline long int lrintf(float flt) {
- return (long int)floorf(flt+0.5f);
+ __inline long int lrint (double flt) {
+ return (long int)(flt + 0.5);
}
+# endif
#endif
-#endif
+#define fuzzyEpsilon64 (0.0000005)
+#define fuzzyEpsilon32 (0.00001f)
-#define fuzzyEpsilon (0.00001f)
/**
This value should not be tested against directly, instead
G3D::isNan() and G3D::isFinite() will return reliable results. */
@@ -147,23 +160,14 @@ inline double twoPi() {
return 6.28318531;
}
-typedef signed char int8;
-typedef unsigned char uint8;
-typedef short int16;
-typedef unsigned short uint16;
-typedef int int32;
-typedef unsigned int uint32;
-
-#ifdef _MSC_EXTENSIONS
- typedef __int64 int64;
- typedef unsigned __int64 uint64;
-#elif ! defined(_MSC_VER)
- typedef int64_t int64;
- typedef uint64_t uint64;
-#else
- typedef long long int64;
- typedef unsigned long long uint64;
-#endif
+typedef int8_t int8;
+typedef uint8_t uint8;
+typedef int16_t int16;
+typedef uint16_t uint16;
+typedef int32_t int32;
+typedef uint32_t uint32;
+typedef int64_t int64;
+typedef uint64_t uint64;
typedef float float32;
typedef double float64;
@@ -207,7 +211,14 @@ inline int iSign(float f) {
return iSign((double)f);
}
+inline double round(double f) {
+ return floor(f + 0.5f);
+}
+inline float round(float f) {
+ return floor(f + 0.5f);
+}
+
/**
Fast round to integer using the lrint routine.
Typically 6x faster than casting to integer.
@@ -256,6 +267,11 @@ inline bool isNaN(int x) {
return false;
}
+inline bool isNaN(uint64 x) {
+ (void)x;
+ return false;
+}
+
/**
Computes x % 3.
*/
@@ -339,6 +355,7 @@ int highestBit(uint32 x);
*/
bool fuzzyEq(double a, double b);
+
/** True if a is definitely not equal to b.
Guaranteed false if a == b.
Possibly false when a != b.*/
@@ -393,6 +410,7 @@ inline double log2(int x) {
* True if num is a power of two.
*/
bool isPow2(int num);
+bool isPow2(uint64 num);
bool isOdd(int num);
bool isEven(int num);
@@ -455,7 +473,7 @@ inline double rsqrt(double x) {
/** @deprecated Use rsq */
inline float rsqrt(float x) {
// TODO: default this to using the SSE2 instruction
- return 1.0 / sqrtf(x);
+ return 1.0f / sqrtf(x);
}
/**
@@ -526,59 +544,59 @@ inline int iCeil (double fValue) {
inline int iClamp(int val, int low, int hi) {
debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
+ if (val <= low) {
+ return low;
+ } else if (val >= hi) {
+ return hi;
+ } else {
+ return val;
+ }
}
//----------------------------------------------------------------------------
inline int16 iClamp(int16 val, int16 low, int16 hi) {
debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
+ if (val <= low) {
+ return low;
+ } else if (val >= hi) {
+ return hi;
+ } else {
+ return val;
+ }
}
//----------------------------------------------------------------------------
inline double clamp(double val, double low, double hi) {
debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
+ if (val <= low) {
+ return low;
+ } else if (val >= hi) {
+ return hi;
+ } else {
+ return val;
+ }
}
inline float clamp(float val, float low, float hi) {
debugAssert(low <= hi);
- if (val <= low) {
- return low;
- } else if (val >= hi) {
- return hi;
- } else {
- return val;
- }
+ if (val <= low) {
+ return low;
+ } else if (val >= hi) {
+ return hi;
+ } else {
+ return val;
+ }
}
//----------------------------------------------------------------------------
inline int iWrap(int val, int hi) {
- if (val < 0) {
- return ((val % hi) + hi) % hi;
- } else {
- return val % hi;
- }
+ if (val < 0) {
+ return ((val % hi) + hi) % hi;
+ } else {
+ return val % hi;
+ }
}
//----------------------------------------------------------------------------
@@ -651,11 +669,11 @@ inline double aTan2 (double fY, double fX) {
inline double sign (double fValue) {
if (fValue > 0.0) {
return 1.0;
- }
+ }
if (fValue < 0.0) {
return -1.0;
- }
+ }
return 0.0;
}
@@ -663,11 +681,11 @@ inline double sign (double fValue) {
inline float sign (float fValue) {
if (fValue > 0.0f) {
return 1.0f;
- }
+ }
if (fValue < 0.0f) {
return -1.0f;
- }
+ }
return 0.0f;
}
@@ -759,6 +777,16 @@ inline bool isPow2(int num) {
return ((num & -num) == num);
}
+inline bool isPow2(uint64 x) {
+ // See http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/, method #9
+ return ((x != 0) && !(x & (x - 1)));
+}
+
+inline bool isPow2(uint32 x) {
+ // See http://www.exploringbinary.com/ten-ways-to-check-if-an-integer-is-a-power-of-two-in-c/, method #9
+ return ((x != 0) && !(x & (x - 1)));
+}
+
inline bool isOdd(int num) {
return (num & 1) == 1;
}
@@ -801,12 +829,31 @@ inline double eps(double a, double b) {
(void)b;
const double aa = abs(a) + 1.0;
if (aa == inf()) {
- return fuzzyEpsilon;
+ return fuzzyEpsilon64;
} else {
- return fuzzyEpsilon * aa;
+ return fuzzyEpsilon64 * aa;
}
}
+inline float eps(float a, float b) {
+ // For a and b to be nearly equal, they must have nearly
+ // the same magnitude. This means that we can ignore b
+ // since it either has the same magnitude or the comparison
+ // will fail anyway.
+ (void)b;
+ const float aa = (float)abs(a) + 1.0f;
+ if (aa == inf()) {
+ return fuzzyEpsilon32;
+ } else {
+ return fuzzyEpsilon32 * aa;
+ }
+}
+
+
+inline bool fuzzyEq(float a, float b) {
+ return (a == b) || (abs(a - b) <= eps(a, b));
+}
+
inline bool fuzzyEq(double a, double b) {
return (a == b) || (abs(a - b) <= eps(a, b));
}
@@ -850,9 +897,47 @@ inline uint16 flipEndian16(const uint16 x) {
return (x << 8) | ((x & 0xFF00) >> 8);
}
+/** The GLSL smoothstep function */
+inline float smoothstep(float edge0, float edge1, float x) {
+ // Scale, bias and saturate x to 0..1 range
+ x = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
+
+ // Evaluate polynomial
+ return x * x * (3 - 2 * x);
+}
+
+
+/** Perlin's C2 continous variation on smoothstep() */
+inline float smootherstep(float edge0, float edge1, float x) {
+
+ // Scale, and saturate x to 0..1 range
+ x = clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
+
+ // Evaluate polynomial
+ return x * x * x * (x * (x * 6 - 15) + 10);
+}
+
+
+/** Computes |b|^e * sign(b) */
+inline float signedPow(float b, float e) {
+ return sign(b) * powf(fabsf(b), e);
+}
+
+
+/** Computes |b|^e * sign(b) */
+inline double signedPow(double b, double e) {
+ return sign(b) * pow(abs(b), e);
+}
+
} // namespace
+namespace std {
+inline int pow(int a, int b) {
+ return (int)pow(double(a), double(b));
+}
+
+}
#ifdef _MSC_VER
# pragma warning (pop)
#endif
diff --git a/dep/g3dlite/include/G3D/netheaders.h b/dep/g3dlite/include/G3D/netheaders.h
index a82d7c36f36..cff3823442e 100644
--- a/dep/g3dlite/include/G3D/netheaders.h
+++ b/dep/g3dlite/include/G3D/netheaders.h
@@ -3,7 +3,7 @@
#include "G3D/platform.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
# if (G3D_WINSOCK_MAJOR_VERSION == 2)
# include <winsock2.h>
# elif (G3D_WINSOCK_MAJOR_VERSION == 1)
diff --git a/dep/g3dlite/include/G3D/networkHelpers.h b/dep/g3dlite/include/G3D/networkHelpers.h
index 7a532d71ee6..e3168c24343 100644
--- a/dep/g3dlite/include/G3D/networkHelpers.h
+++ b/dep/g3dlite/include/G3D/networkHelpers.h
@@ -85,7 +85,7 @@
#ifndef _SOCKLEN_T
-# if defined(G3D_WIN32) || defined(G3D_OSX)
+# if defined(G3D_WINDOWS) || defined(G3D_OSX)
typedef int socklen_t;
# endif
#endif
diff --git a/dep/g3dlite/include/G3D/platform.h b/dep/g3dlite/include/G3D/platform.h
index 65616f0b53e..17e3bf279eb 100644
--- a/dep/g3dlite/include/G3D/platform.h
+++ b/dep/g3dlite/include/G3D/platform.h
@@ -1,22 +1,26 @@
/**
- @file platform.h
+ \file platform.h
\#defines for platform specific issues.
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-06-09
- @edited 2010-08-11
+ Copyright 2000-2012, Morgan McGuire.
+ All rights reserved.
+
+ \created 2003-06-09
+ \edited 2013-01-03
*/
#ifndef G3D_platform_h
#define G3D_platform_h
/**
+ \def G3D_VER
The version number of G3D in the form: MmmBB ->
version M.mm [beta BB]
*/
-#define G3D_VER 80100
+#define G3D_VER 90000
// fatal error for unsupported architectures
#if defined(__powerpc__)
@@ -31,13 +35,15 @@
# undef _DEBUG
#endif
-/** @def G3D_DEBUG()
+/** \def G3D_DEBUG
Defined if G3D is built in debug mode. */
#if !defined(G3D_DEBUG) && (defined(_DEBUG) || defined(G3D_DEBUGRELEASE))
# define G3D_DEBUG
#endif
-/** These control the version of Winsock used by G3D.
+/**
+\def G3D_WINSOCK_MAJOR_VERSION
+These control the version of Winsock used by G3D.
Version 2.0 is standard for G3D 6.09 and later.
Version 1.1 is standard for G3D 6.08 and earlier.
*/
@@ -49,10 +55,15 @@
#define __fastcall
#endif
+/** \def G3D_WINDOWS*/
+/** \def G3D_FREEBSD2*/
+/** \def G3D_LINUX*/
+/** \def G3D_OSX */
+
#ifdef _MSC_VER
- #define G3D_WIN32
+# define G3D_WINDOWS
#elif defined(__MINGW32__)
- #define G3D_WIN32
+ #define G3D_WINDOWS
#undef __MSVCRT_VERSION__
#define __MSVCRT_VERSION__ 0x0601
#include <windows.h>
@@ -61,8 +72,6 @@
#define G3D_LINUX
#elif defined(__linux__)
#define G3D_LINUX
-#elif defined(__CYGWIN__)
- #define G3D_LINUX
#elif defined(__APPLE__)
#define G3D_LINUX
@@ -70,25 +79,26 @@
// pi as a constant, which creates a conflict with G3D
#define __FP__
#else
- #error Unknown platform
+ #error Unknown platform
+#endif
+
+/** \def G3D_64BIT */
+/** \def G3D_32BIT */
+
+
+
+/** Define the g++ thread-local syntax on all platforms (since the MSVC version would be hard to emulate with a macro) */
+#if defined(_MSC_VER)
+# define __thread __declspec(thread)
#endif
// Detect 64-bit under various compilers
#if (defined(_M_X64) || defined(_WIN64) || defined(__LP64__) || defined(_LP64))
# define G3D_64BIT
- #if defined(WIN32)
- #include <intrin.h>
- #endif
#else
# define G3D_32BIT
#endif
-// Strongly encourage inlining on gcc
-#ifdef __GNUC__
-#define inline __inline__
-#endif
-
-
// Verify that the supported compilers are being used and that this is a known
// processor.
@@ -96,13 +106,14 @@
# ifndef __GNUC__
# error G3D only supports the gcc compiler on Linux.
# endif
+# define G3D_NO_FFMPEG
#endif
#ifdef G3D_OSX
# ifndef __GNUC__
# error G3D only supports the gcc compiler on OS X.
# endif
-
+
# if defined(__i386__)
# define G3D_OSX_INTEL
# elif defined(__PPC__)
@@ -115,11 +126,13 @@
#ifdef _MSC_VER
+// Microsoft Visual C++ 10.0 = 1600
+// Microsoft Visual C++ 9.0 = 1500
// Microsoft Visual C++ 8.0 ("Express") = 1400
-// Microsoft Visual C++ 7.1 ("2003") _MSC_VER = 1310
-// Microsoft Visual C++ 7.0 ("2002") _MSC_VER = 1300
-// Microsoft Visual C++ 6.0 _MSC_VER = 1200
-// Microsoft Visual C++ 5.0 _MSC_VER = 1100
+// Microsoft Visual C++ 7.1 ("2003") _MSC_VER = 1310
+// Microsoft Visual C++ 7.0 ("2002") _MSC_VER = 1300
+// Microsoft Visual C++ 6.0 _MSC_VER = 1200
+// Microsoft Visual C++ 5.0 _MSC_VER = 1100
// Turn off warnings about deprecated C routines
# pragma warning (disable : 4996)
@@ -128,8 +141,16 @@
// for debug assertions in inlined methods.
# pragma warning (disable : 4127)
-/** @def G3D_DEPRECATED()
- Creates deprecated warning. */
+/** \def G3D_DEPRECATED()
+ Creates deprecated warning at compile time when used.
+
+ Example:
+ \code
+ int G3D_DEPRECATED sum(int a, int b) {
+ return a + b;
+ }
+ \endcode
+ */
# define G3D_DEPRECATED __declspec(deprecated)
// Prevent Winsock conflicts by hiding the winsock API
@@ -140,14 +161,12 @@
// Disable 'name too long for browse information' warning
# pragma warning (disable : 4786)
-// TODO: remove
-# pragma warning (disable : 4244)
# define restrict
/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
Enables printf parameter validation on gcc. */
-# define G3D_CHECK_PRINTF_ARGS
+# define G3D_CHECK_PRINTF_ARGS
/** @def G3D_CHECK_PRINTF_METHOD_ARGS()
Enables printf parameter validation on gcc. */
@@ -173,50 +192,34 @@
// DLL runtime
#ifndef _DLL
- #define _DLL
+ #define _DLL
#endif
// Multithreaded runtime
#ifndef _MT
- #define _MT 1
+ #define _MT 1
#endif
// Ensure that we aren't forced into the static lib
#ifdef _STATIC_CPPLIB
- #undef _STATIC_CPPLIB
- #endif
-
- #ifdef _DEBUG
- #pragma comment (linker, "/NODEFAULTLIB:LIBCMTD.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPMTD.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPD.LIB")
- #pragma comment (linker, "/DEFAULTLIB:MSVCPRTD.LIB")
- #pragma comment(linker, "/NODEFAULTLIB:LIBCD.LIB")
- #pragma comment(linker, "/DEFAULTLIB:MSVCRTD.LIB")
- #else
- #pragma comment(linker, "/NODEFAULTLIB:LIBC.LIB")
- #pragma comment(linker, "/DEFAULTLIB:MSVCRT.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCMT.LIB")
- #pragma comment (linker, "/NODEFAULTLIB:LIBCPMT.LIB")
- #pragma comment(linker, "/NODEFAULTLIB:LIBCP.LIB")
- #pragma comment (linker, "/DEFAULTLIB:MSVCPRT.LIB")
+ #undef _STATIC_CPPLIB
#endif
- // Now set up external linking
-
-# ifdef _DEBUG
- // zlib was linked against the release MSVCRT; force
- // the debug version.
-# pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB")
-# endif
+#ifdef _DEBUG
+ // Some of the support libraries are always built in Release.
+ // Make sure the debug runtime library is linked in
+ #pragma comment(linker, "/NODEFAULTLIB:MSVCRT.LIB")
+ #pragma comment(linker, "/NODEFAULTLIB:MSVCPRT.LIB")
+#endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN 1
# endif
-
-# define NOMINMAX 1
+# ifndef NOMINMAX
+# define NOMINMAX 1
+# endif
# ifndef _WIN32_WINNT
# define _WIN32_WINNT 0x0500
# endif
@@ -230,8 +233,9 @@
# endif
-/** @def G3D_START_AT_MAIN()
- Defines necessary wrapper around WinMain on Windows to allow transfer of execution to main(). */
+/** \def G3D_START_AT_MAIN()
+ Makes Windows programs using the WINDOWS subsystem invoke main() at program start by
+ defining a WinMain(). Does nothing on other operating systems.*/
# define G3D_START_AT_MAIN()\
int WINAPI G3D_WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw);\
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\
@@ -299,7 +303,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\
/**
- @def STR(expression)
+ \def STR(expression)
Creates a string from the expression. Frequently used with G3D::Shader
to express shading programs inline.
@@ -319,26 +323,96 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrev, LPSTR szCmdLine, int sw) {\
# define PRAGMA(x) _Pragma(#x)
#endif
-/** @def G3D_BEGIN_PACKED_CLASS(byteAlign)
- Switch to tight alignment
+/** \def G3D_BEGIN_PACKED_CLASS(byteAlign)
+ Switch to tight alignment.
+
+ \code
+ G3D_BEGIN_PACKED_CLASS(1)
+ ThreeBytes {
+ public:
+ uint8 a, b, c;
+ }
+ G3D_END_PACKED_CLASS(1)
+ \endcode
+
+
See G3D::Color3uint8 for an example.*/
-#ifdef _MSC_VER
-# define G3D_BEGIN_PACKED_CLASS(byteAlign) PRAGMA( pack(push, byteAlign) )
+#ifdef __GNUC__
+# define G3D_BEGIN_PACKED_CLASS(byteAlign) class __attribute((__packed__))
+#elif defined(_MSC_VER)
+# define G3D_BEGIN_PACKED_CLASS(byteAlign) PRAGMA( pack(push, byteAlign) ) class
#else
-# define G3D_BEGIN_PACKED_CLASS(byteAlign)
+# define G3D_BEGIN_PACKED_CLASS(byteAlign) class
#endif
-/** @def G3D_END_PACKED_CLASS(byteAlign)
+/** \def G3D_END_PACKED_CLASS(byteAlign)
End switch to tight alignment
+
See G3D::Color3uint8 for an example.*/
-#ifdef _MSC_VER
-# define G3D_END_PACKED_CLASS(byteAlign) ; PRAGMA( pack(pop) )
-#elif defined(__GNUC__)
+#ifdef __GNUC__
# define G3D_END_PACKED_CLASS(byteAlign) __attribute((aligned(byteAlign))) ;
+#elif defined(_MSC_VER)
+# define G3D_END_PACKED_CLASS(byteAlign) ; PRAGMA( pack(pop) )
#else
# define G3D_END_PACKED_CLASS(byteAlign) ;
#endif
-// Header guard
+// Bring in shared_ptr and weak_ptr
+#if (defined(__GNUC__) && defined(__APPLE__)) || defined(__linux__)
+#include <ciso646> // Defines _LIBCC_VERSION if linking against libc++ or does nothing
#endif
+#if (!defined(_LIBCPP_VERSION) && defined(__APPLE__)) || (!defined(_LIBCPP_VERSION) && defined(__linux__))
+# include <tr1/memory>
+ using std::tr1::shared_ptr;
+ using std::tr1::weak_ptr;
+ using std::tr1::dynamic_pointer_cast;
+ using std::tr1::static_pointer_cast;
+ using std::tr1::enable_shared_from_this;
+#else
+# include <memory>
+ using std::shared_ptr;
+ using std::weak_ptr;
+ using std::dynamic_pointer_cast;
+ using std::static_pointer_cast;
+ using std::enable_shared_from_this;
+#endif
+
+namespace G3D {
+ /** Options for initG3D and initGLG3D. */
+ class G3DSpecification {
+ public:
+ /**
+ \brief Should G3D spawn its own network thread?
+
+ If true, G3D will spawn a thread for network management on the first invocation of G3D::NetServer::create or
+ G3D::NetConnection::connectToServer.
+
+ If false and networking is used, the application must explicitly invoke G3D::serviceNetwork() regularly to allow the network
+ code to run.
+
+ In either case, the network API is threadsafe.
+
+ Default: true.
+ */
+ bool threadedNetworking;
+
+ G3DSpecification() : threadedNetworking(true) {}
+
+ virtual ~G3DSpecification() {}
+ };
+
+
+ namespace _internal {
+ /** Set by initG3D, defined in initG3D.cpp */
+ G3DSpecification& g3dInitializationSpecification();
+ }
+}
+
+// See http://stackoverflow.com/questions/2670816/how-can-i-use-the-compile-time-constant-line-in-a-string
+// For use primarily with NUMBER_TO_STRING(__LINE__)
+#define NUMBER_TO_STRING(x) NUMBER_TO_STRING2(x)
+#define NUMBER_TO_STRING2(x) #x
+#define __LINE_AS_STRING__ NUMBER_TO_STRING(__LINE__)
+
+#endif // Header guard
diff --git a/dep/g3dlite/include/G3D/serialize.h b/dep/g3dlite/include/G3D/serialize.h
index 2382c0ee0fd..f4a28611701 100644
--- a/dep/g3dlite/include/G3D/serialize.h
+++ b/dep/g3dlite/include/G3D/serialize.h
@@ -1,18 +1,68 @@
-#ifndef G3D_SERIALIZE_H
-#define G3D_SERIALIZE_H
+#ifndef G3D_serialize_h
+#define G3D_serialize_h
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/Array.h"
+#include <string>
namespace G3D {
+
-
+inline void serialize(const std::string& s, BinaryOutput& b) {
+ b.writeString32(s);
+}
+
+inline void deserialize(std::string& s, BinaryInput& b) {
+ s = b.readString32();
+}
+
+inline void serialize(const int32& i, BinaryOutput& b) {
+ b.writeInt32(i);
+}
+
+inline void deserialize(int32& i, BinaryInput& b) {
+ i = b.readInt32();
+}
+
+inline void serialize(const uint32& i, BinaryOutput& b) {
+ b.writeUInt32(i);
+}
+
+inline void deserialize(uint32& i, BinaryInput& b) {
+ i = b.readUInt32();
+}
+
+inline void serialize(const bool& i, BinaryOutput& b) {
+ b.writeBool8(i);
+}
+
+inline void deserialize(bool& i, BinaryInput& b) {
+ i = b.readBool8();
+}
+
+inline void serialize(const float32& f, BinaryOutput& b) {
+ b.writeFloat32(f);
+}
+
+inline void deserialize(float32& f, BinaryInput& b) {
+ f = b.readFloat32();
+}
+
+inline void serialize(const float64& f, BinaryOutput& b) {
+ b.writeFloat64(f);
+}
+
+inline void deserialize(float64& f, BinaryInput& b) {
+ f = b.readFloat64();
+}
+
+/** serialize(const T&, BinaryOutput&) must have been overridden as well */
template<typename T>
void serialize(const Array<T>& array, BinaryOutput& b) {
b.writeInt32(array.size());
for (int i = 0; i < array.size(); ++i) {
- serialize(array[i], b);
+ serialize(array[i], b);
}
}
@@ -25,6 +75,6 @@ void deserialize(Array<T>& array, BinaryInput& b) {
}
}
-}
+} // G3D
-#endif
+#endif //G3D_serialize_h
diff --git a/dep/g3dlite/include/G3D/stringutils.h b/dep/g3dlite/include/G3D/stringutils.h
index 42a4886521a..01ac674f336 100644
--- a/dep/g3dlite/include/G3D/stringutils.h
+++ b/dep/g3dlite/include/G3D/stringutils.h
@@ -31,53 +31,72 @@ void parseCommaSeparated(const std::string s, Array<std::string>& array, bool st
/** Finds the index of the first '\\' or '/' character, starting at index \a start.
\sa G3D::findLastSlash, G3D::isSlash
*/
-inline int findSlash(const std::string& f, int start = 0) {
- int i = f.find('/', start);
- int j = f.find('\\', start);
- if (((i != -1) && (i < j)) || (j == -1)) {
+inline size_t findSlash(const std::string& f, size_t start = 0) {
+ size_t i = f.find('/', start);
+ size_t j = f.find('\\', start);
+ if ((i != std::string::npos) && (i < j)) {
return i;
} else {
return j;
}
}
+/** \brief Returns the larger string index, ignoring std::string::npos. */
+inline size_t maxNotNPOS(size_t i, size_t j) {
+ if (i == std::string::npos) {
+ return j;
+ } else if (j == std::string::npos) {
+ return i;
+ } else {
+ return max(i, j);
+ }
+}
/** Finds the index of the first '\\' or '/' character, starting at index \a start (if \a start is -1, starts at the end of the string).
\sa G3D::findSlash, G3D::isSlash
*/
-inline int findLastSlash(const std::string& f, int start = -1) {
- if (start == -1) {
+inline size_t findLastSlash(const std::string& f, size_t start = std::string::npos) {
+ if (start == std::string::npos) {
start = f.length() - 1;
}
- int i = f.rfind('/', start);
- int j = f.rfind('\\', start);
- return max(i, j);
+ size_t i = f.rfind('/', start);
+ size_t j = f.rfind('\\', start);
+ return maxNotNPOS(i, j);
}
+
+/** Returns a string which is \a s, with all instances of \a pattern replaced */
+std::string replace(const std::string& s, const std::string& pattern, const std::string& replacement);
+
+/** Returns true if \a s is a valid C++ identifier */
+bool isValidIdentifier(const std::string& s);
+
/**
- Returns true if the test string begins with the pattern string.
+ \brief Returns true if the test string begins with the pattern string.
*/
-bool beginsWith(
- const std::string& test,
+bool beginsWith
+ (const std::string& test,
const std::string& pattern);
/**
- Returns true if the test string ends with the pattern string.
+ \brief Returns true if the test string ends with the pattern string.
*/
-bool endsWith(
- const std::string& test,
+bool endsWith
+ (const std::string& test,
const std::string& pattern);
/**
- Produces a new string that is the input string
+ \brief Produces a new string that is the input string
wrapped at a certain number of columns (where
the line is broken at the latest space before the
column limit.) Platform specific NEWLINEs
are inserted to wrap.
+
+ \sa G3D::GFont::wordWrapCut, G3D::TextOutput::Settings::WordWrapMode
*/
-std::string wordWrap(
- const std::string& input,
+std::string wordWrap
+ (const std::string& input,
int numCols);
/**
@@ -161,6 +180,17 @@ inline bool isQuote(const unsigned char c) {
return (c == '\'') || (c == '\"');
}
+/** Number of new lines in the given string */
+inline int countNewlines(const std::string& s) {
+ int c = 0;
+ for (int i = 0; i < (int)s.size(); ++i) {
+ if (s[i] == '\n') {
+ ++c;
+ }
+ }
+ return c;
+}
+
}; // namespace
#endif
diff --git a/dep/g3dlite/include/G3D/uint128.h b/dep/g3dlite/include/G3D/uint128.h
index da1af3ec272..6698d88f0c1 100644
--- a/dep/g3dlite/include/G3D/uint128.h
+++ b/dep/g3dlite/include/G3D/uint128.h
@@ -20,31 +20,30 @@ namespace G3D {
class uint128 {
public:
- G3D::uint64 hi;
- G3D::uint64 lo;
+ G3D::uint64 hi;
+ G3D::uint64 lo;
uint128(const uint64& lo);
- uint128(const uint64& hi, const uint64& lo);
-
- uint128& operator+=(const uint128& x);
-
- uint128& operator*=(const uint128& x);
-
- uint128& operator^=(const uint128& x);
-
- uint128& operator&=(const uint128& x);
-
- uint128& operator|=(const uint128& x);
-
- bool operator==(const uint128& x);
-
+ uint128(const uint64& hi, const uint64& lo);
+
+ uint128& operator+=(const uint128& x);
+
+ uint128& operator*=(const uint128& x);
+
+ uint128& operator^=(const uint128& x);
+
+ uint128& operator&=(const uint128& x);
+
+ uint128& operator|=(const uint128& x);
+
+ bool operator==(const uint128& x);
+
uint128& operator>>=(const int x);
uint128& operator<<=(const int x);
-
+
uint128 operator&(const uint128& x);
-
};
}
diff --git a/dep/g3dlite/include/G3D/units.h b/dep/g3dlite/include/G3D/units.h
index 2e30304dc62..694576f3d25 100644
--- a/dep/g3dlite/include/G3D/units.h
+++ b/dep/g3dlite/include/G3D/units.h
@@ -1,10 +1,10 @@
/**
- @file units.h
+ \file G3D/units.h
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-08-21
- @edited 2009-08-21
+ \created 2009-08-21
+ \edited 2011-07-08
*/
#ifndef G3D_units_h
#define G3D_units_h
@@ -46,7 +46,7 @@ inline float meters() {
/** 1000 m */
inline float kilometers() {
- return 100.0f;
+ return 1000.0f;
}
/** 0.0254 m */
@@ -120,7 +120,37 @@ inline float years() {
///////////////////////////////////////////
+/** SI unit of mass */
+inline float kilograms() {
+ return 1.0f;
+}
+
+///////////////////////////////////////////
+
+/** 1 kg m / s^2 */
+inline float newtons() {
+ return 1.0f;
+}
+
+///////////////////////////////////////////
+
+/** SI unit of power: W = J/s*/
+inline float watts() {
+ return 1.0;
}
+
+/** SI unit of energy: J = N*m */
+inline float joules() {
+ return 1.0;
}
+/** Unit of solid angle measure. A sphere subtends 4 * pi sr. */
+inline float steradians() {
+ return 1.0;
+}
+
+
+} // units
+} // G3D
+
#endif
diff --git a/dep/g3dlite/include/G3D/unorm16.h b/dep/g3dlite/include/G3D/unorm16.h
new file mode 100644
index 00000000000..d879eb0630b
--- /dev/null
+++ b/dep/g3dlite/include/G3D/unorm16.h
@@ -0,0 +1,180 @@
+/**
+ \file G3D/unorm16.h
+
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ \created 2012-03-02 by Zina Cigolle
+ \edited 2012-03-02
+
+ Copyright 2000-2012, Morgan McGuire.
+ All rights reserved.
+ */
+#ifndef G3D_unorm16_h
+#define G3D_unorm16_h
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+
+namespace G3D {
+
+
+/** Represents numbers on [0, 1] in 16 bits as an unsigned normalized
+ 0.8 fixed-point value using the same encoding scheme as OpenGL.
+
+ Note that arithmetic operations may over and under-flow, just like
+ uint16 arithmetic.
+
+ OpenGL specifications can be found here:
+ http://www.opengl.org/registry/specs/ARB/shading_language_packing.txt
+
+*/
+G3D_BEGIN_PACKED_CLASS(1)
+unorm16 {
+private:
+ uint16 m_bits;
+
+ /** Private to prevent illogical conversions without explicitly
+ stating that the input should be treated as bits; see fromBits. */
+ explicit unorm16(uint16 b) : m_bits(b) {}
+
+public:
+
+ /** Equivalent to: \code unorm16 u = reinterpret_cast<const unorm16&>(255);\endcode */
+ static unorm16 fromBits(uint16 b) {
+ return unorm16(b);
+ }
+
+ /** \copydoc fromBits */
+ static unorm16 reinterpretFrom(uint16 b) {
+ return unorm16(b);
+ }
+
+ unorm16() : m_bits(0) {}
+
+ unorm16(const unorm16& other) : m_bits(other.m_bits) {}
+
+ explicit unorm16(const class Any& a);
+
+ class Any toAny() const;
+
+ /** Maps f to round(f * 65535).*/
+ explicit unorm16(float f) {
+ m_bits = uint16(clamp(f, 0.0f, 1.0f) * 65535.0f + 0.5f);
+ }
+
+ explicit unorm16(double f) {
+ m_bits = uint16(clamp(f, 0.0, 1.0) * 65535.0 + 0.5);
+ }
+
+ /** Returns a number on [0.0f, 1.0f] */
+ operator float() const {
+ return float(m_bits) * (1.0f / 65535.0f);
+ }
+
+ operator double() const {
+ return double(m_bits) * (1.0 / 65535.0);
+ }
+
+ static unorm16 one() {
+ return fromBits(65535);
+ }
+
+ static unorm16 zero() {
+ return fromBits(0);
+ }
+
+ /**\brief Returns the underlying bits in this representation.
+ Equivalent to:
+ \code uint16 i = reinterpret_cast<const uint16&>(u); \endcode */
+ uint16 bits() const {
+ return m_bits;
+ }
+
+ /** \copydoc bits */
+ uint16 reinterpretAsUInt16() const {
+ return m_bits;
+ }
+
+ bool operator>(const unorm16 other) const {
+ return m_bits > other.m_bits;
+ }
+
+ bool operator<(const unorm16 other) const {
+ return m_bits < other.m_bits;
+ }
+
+ bool operator>=(const unorm16 other) const {
+ return m_bits >= other.m_bits;
+ }
+
+ bool operator<=(const unorm16 other) const {
+ return m_bits <= other.m_bits;
+ }
+
+ bool operator==(const unorm16 other) const {
+ return m_bits <= other.m_bits;
+ }
+
+ bool operator!=(const unorm16 other) const {
+ return m_bits != other.m_bits;
+ }
+
+ unorm16 operator+(const unorm16 other) const {
+ return unorm16(uint16(m_bits + other.m_bits));
+ }
+
+ unorm16& operator+=(const unorm16 other) {
+ m_bits += other.m_bits;
+ return *this;
+ }
+
+ unorm16 operator-(const unorm16 other) const {
+ return unorm16(uint16(m_bits - other.m_bits));
+ }
+
+ unorm16& operator-=(const unorm16 other) {
+ m_bits -= other.m_bits;
+ return *this;
+ }
+
+ unorm16 operator*(const int i) const {
+ return unorm16(uint16(m_bits * i));
+ }
+
+ unorm16& operator*=(const int i) {
+ m_bits *= i;
+ return *this;
+ }
+
+ unorm16 operator/(const int i) const {
+ return unorm16(uint16(m_bits / i));
+ }
+
+ unorm16& operator/=(const int i) {
+ m_bits /= i;
+ return *this;
+ }
+
+ unorm16 operator<<(const int i) const {
+ return unorm16((uint16)(m_bits << i));
+ }
+
+ unorm16& operator<<=(const int i) {
+ m_bits <<= i;
+ return *this;
+ }
+
+ unorm16 operator>>(const int i) const {
+ return unorm16(uint16(m_bits >> i));
+ }
+
+ unorm16& operator>>=(const int i) {
+ m_bits >>= i;
+ return *this;
+ }
+}
+G3D_END_PACKED_CLASS(1)
+
+} // namespace G3D
+
+#endif // G3D_unorm16
diff --git a/dep/g3dlite/include/G3D/unorm8.h b/dep/g3dlite/include/G3D/unorm8.h
new file mode 100644
index 00000000000..b62d100abb4
--- /dev/null
+++ b/dep/g3dlite/include/G3D/unorm8.h
@@ -0,0 +1,177 @@
+/**
+ \file G3D/unorm8.h
+
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+
+ \created 2011-08-11
+ \edited 2011-08-11
+
+ Copyright 2000-2012, Morgan McGuire.
+ All rights reserved.
+ */
+#ifndef G3D_unorm8_h
+#define G3D_unorm8_h
+
+#include "G3D/platform.h"
+#include "G3D/g3dmath.h"
+
+namespace G3D {
+
+
+/** Represents numbers on [0, 1] in 8 bits as an unsigned normalized
+ 0.8 fixed-point value using the same encoding scheme as OpenGL.
+
+ OpenGL specifications can be found here:
+ <www.opengl.org/registry/specs/ARB/shading_language_packing.txt>
+
+ Note that arithmetic operations may over and under-flow, just like
+ uint8 arithmetic.
+
+
+*/
+G3D_BEGIN_PACKED_CLASS(1)
+unorm8 {
+private:
+ uint8 m_bits;
+
+ /** Private to prevent illogical conversions without explicitly
+ stating that the input should be treated as bits; see fromBits. */
+ explicit unorm8(uint8 b) : m_bits(b) {}
+
+public:
+
+ /** Equivalent to: \code unorm8 u = reinterpret_cast<const unorm8&>(255);\endcode */
+ static unorm8 fromBits(uint8 b) {
+ return unorm8(b);
+ }
+
+ /** \copydoc fromBits */
+ static unorm8 reinterpretFrom(uint8 b) {
+ return unorm8(b);
+ }
+
+ unorm8() : m_bits(0) {}
+
+ unorm8(const unorm8& other) : m_bits(other.m_bits) {}
+
+ /** Maps f to round(f * 255).*/
+ explicit unorm8(float f) {
+ m_bits = (uint8)(clamp(f, 0.0f, 1.0f) * 255.0f + 0.5f);
+ }
+
+ explicit unorm8(double f) {
+ m_bits = iClamp(int(f * 255.0f + 0.5f), 0, 255);
+ }
+
+ /** Returns a number on [0.0f, 1.0f] */
+ operator float() const {
+ return float(m_bits) * (1.0f / 255.0f);
+ }
+
+ operator double() const {
+ return double(m_bits) * (1.0 / 255.0);
+ }
+
+ static unorm8 one() {
+ return fromBits(255);
+ }
+
+ static unorm8 zero() {
+ return fromBits(0);
+ }
+
+ /**\brief Returns the underlying bits in this representation.
+ Equivalent to:
+ \code uint8 i = reinterpret_cast<const uint8&>(u); \endcode */
+ uint8 bits() const {
+ return m_bits;
+ }
+
+ /** \copydoc bits */
+ uint8 reinterpretAsUInt8() const {
+ return m_bits;
+ }
+
+ bool operator>(const unorm8 other) const {
+ return m_bits > other.m_bits;
+ }
+
+ bool operator<(const unorm8 other) const {
+ return m_bits < other.m_bits;
+ }
+
+ bool operator>=(const unorm8 other) const {
+ return m_bits >= other.m_bits;
+ }
+
+ bool operator<=(const unorm8 other) const {
+ return m_bits <= other.m_bits;
+ }
+
+ bool operator==(const unorm8 other) const {
+ return m_bits <= other.m_bits;
+ }
+
+ bool operator!=(const unorm8 other) const {
+ return m_bits != other.m_bits;
+ }
+
+ unorm8 operator+(const unorm8 other) const {
+ return unorm8(uint8(m_bits + other.m_bits));
+ }
+
+ unorm8& operator+=(const unorm8 other) {
+ m_bits += other.m_bits;
+ return *this;
+ }
+
+ unorm8 operator-(const unorm8 other) const {
+ return unorm8(uint8(m_bits - other.m_bits));
+ }
+
+ unorm8& operator-=(const unorm8 other) {
+ m_bits -= other.m_bits;
+ return *this;
+ }
+
+ unorm8 operator*(const int i) const {
+ return unorm8(uint8(m_bits * i));
+ }
+
+ unorm8& operator*=(const int i) {
+ m_bits *= i;
+ return *this;
+ }
+
+ unorm8 operator/(const int i) const {
+ return unorm8(uint8(m_bits / i));
+ }
+
+ unorm8& operator/=(const int i) {
+ m_bits /= i;
+ return *this;
+ }
+
+ unorm8 operator<<(const int i) const {
+ return unorm8((uint8)(m_bits << i));
+ }
+
+ unorm8& operator<<=(const int i) {
+ m_bits <<= i;
+ return *this;
+ }
+
+ unorm8 operator>>(const int i) const {
+ return unorm8(uint8(m_bits >> i));
+ }
+
+ unorm8& operator>>=(const int i) {
+ m_bits >>= i;
+ return *this;
+ }
+}
+G3D_END_PACKED_CLASS(1)
+
+} // namespace G3D
+
+#endif // G3D_unorm8
diff --git a/dep/g3dlite/source/AABox.cpp b/dep/g3dlite/source/AABox.cpp
index 8e66456c013..72695b48743 100644
--- a/dep/g3dlite/source/AABox.cpp
+++ b/dep/g3dlite/source/AABox.cpp
@@ -1,10 +1,13 @@
/**
- @file AABox.cpp
+ \file G3D.lib/source/AABox.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-01-10
- @edited 2006-01-11
+ \created 2004-01-10
+ \edited 2013-06-11
+
+ Copyright 2000-2013, Morgan McGuire.
+ All rights reserved.
*/
#include "G3D/platform.h"
@@ -14,10 +17,53 @@
#include "G3D/Sphere.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/Any.h"
namespace G3D {
+AABox::AABox(const Any& a) {
+ if (a.name() == "AABox::empty") {
+ *this = AABox::empty();
+ } else if (a.name() == "AABox::inf") {
+ *this = AABox::inf();
+ } else {
+ a.verifyName("AABox");
+ a.verifyType(Any::ARRAY);
+ if (a.size() == 1) {
+ *this = AABox(Point3(a[0]));
+ } else if (a.size() == 2) {
+ set(Point3(a[0]), Point3(a[1]));
+ } else {
+ a.verify(false, "AABox must recieve exactly 1 or two arguments.");
+ }
+ }
+}
+
+
+Any AABox::toAny() const {
+ if (isEmpty()) {
+ return Any(Any::ARRAY, "AABox::empty");
+ } else if (! isFinite()) {
+ return Any(Any::ARRAY, "AABox::inf");
+ } else {
+ Any a(Any::ARRAY, "AABox");
+ if (lo == hi) {
+ a.append(lo);
+ } else {
+ a.append(lo, hi);
+ }
+ return a;
+ }
+}
+
+
+const AABox& AABox::empty() {
+ static const AABox b;
+ return b;
+}
+
+
const AABox& AABox::maxFinite() {
static const AABox b = AABox(Vector3::minFinite(),
Vector3::maxFinite());
@@ -56,6 +102,13 @@ void AABox::deserialize(class BinaryInput& b) {
}
+void AABox::merge(const Box& b) {
+ AABox aab;
+ b.getBounds(aab);
+ merge(aab);
+}
+
+
void AABox::split(const Vector3::Axis& axis, float location, AABox& low, AABox& high) const {
// Low, medium, and high along the chosen axis
float L = G3D::min(location, lo[axis]);
@@ -139,11 +192,11 @@ bool AABox::intersects(const AABox& other) const {
int AABox::dummy = 0;
-bool AABox::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask,
- uint32& childMask) const {
+bool AABox::culledBy
+ (const Array<Plane>& plane,
+ int& cullingPlane,
+ const uint32 _inMask,
+ uint32& childMask) const {
uint32 inMask = _inMask;
assert(plane.size() < 31);
@@ -159,13 +212,13 @@ bool AABox::culledBy(
(abs(hi.z) < G3D::finf());
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ Vector3 corner;
int numContained = 0;
int v = 0;
@@ -173,12 +226,12 @@ bool AABox::culledBy(
// We can early-out only if we have found one point on each
// side of the plane (i.e. if we are straddling). That
// occurs when (numContained < v) && (numContained > 0)
- for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
+ for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
// Unrolling these 3 if's into a switch decreases performance
// by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
+ corner.x = (v & 1) ? hi.x : lo.x;
+ corner.y = (v & 2) ? hi.y : lo.y;
+ corner.z = (v & 4) ? hi.z : lo.z;
if (finite) { // this branch is highly predictable
if (plane[p].halfSpaceContainsFinite(corner)) {
@@ -189,43 +242,43 @@ bool AABox::culledBy(
++numContained;
}
}
- }
+ }
- if (numContained == 0) {
- // Plane p culled the box
- cullingPlane = p;
+ if (numContained == 0) {
+ // Plane p culled the box
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (numContained < v) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
bool AABox::culledBy(
const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
+ int& cullingPlane,
+ const uint32 _inMask) const {
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
+ uint32 inMask = _inMask;
+ assert(plane.size() < 31);
const bool finite =
(abs(lo.x) < G3D::finf()) &&
@@ -236,58 +289,60 @@ bool AABox::culledBy(
(abs(hi.z) < G3D::finf());
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- bool culled = true;
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ bool culled = true;
+ Vector3 corner;
int v;
- // Assume this plane culls all points. See if there is a point
- // not culled by the plane... early out when at least one point
+ // Assume this plane culls all points. See if there is a point
+ // not culled by the plane... early out when at least one point
// is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
+ for (v = 0; (v < 8) && culled; ++v) {
// Unrolling these 3 if's into a switch decreases performance
// by about 2x
- corner.x = (v & 1) ? hi.x : lo.x;
- corner.y = (v & 2) ? hi.y : lo.y;
- corner.z = (v & 4) ? hi.z : lo.z;
+ corner.x = (v & 1) ? hi.x : lo.x;
+ corner.y = (v & 2) ? hi.y : lo.y;
+ corner.z = (v & 4) ? hi.z : lo.z;
if (finite) { // this branch is highly predictable
culled = ! plane[p].halfSpaceContainsFinite(corner);
} else {
culled = ! plane[p].halfSpaceContains(corner);
}
- }
+ }
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
+ if (culled) {
+ // Plane p culled the box
+ cullingPlane = p;
- return true;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
+
void AABox::getBounds(Sphere& s) const {
s.center = center();
s.radius = extent().length() / 2;
}
-bool AABox::intersects(const class Sphere& sphere) const {
+
+bool AABox::intersects(const Sphere& sphere) const {
double d = 0;
//find the square of the distance
diff --git a/dep/g3dlite/source/Any.cpp b/dep/g3dlite/source/Any.cpp
index 92159bb1862..9204f9efc12 100644
--- a/dep/g3dlite/source/Any.cpp
+++ b/dep/g3dlite/source/Any.cpp
@@ -1,19 +1,21 @@
/**
- @file Any.cpp
+ \file Any.cpp
- @author Morgan McGuire
- @author Shawn Yarbrough
+ \author Morgan McGuire
+ \author Shawn Yarbrough
- @created 2006-06-11
- @edited 2010-07-24
+ \created 2006-06-11
+ \edited 2013-03-29
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
#include "G3D/Any.h"
#include "G3D/TextOutput.h"
#include "G3D/TextInput.h"
+#include "G3D/BinaryOutput.h"
+#include "G3D/BinaryInput.h"
#include "G3D/stringutils.h"
#include "G3D/fileutils.h"
#include "G3D/FileSystem.h"
@@ -21,14 +23,40 @@
#include <iostream>
namespace G3D {
+const char* Any::PAREN = "()";
+const char* Any::BRACKET = "[]";
+const char* Any::BRACE = "{}";
-std::string Any::resolveStringAsFilename() const {
+static bool isContainerType(Any::Type& t) {
+ return (t == Any::ARRAY) || (t == Any::TABLE) || (t == Any::EMPTY_CONTAINER);
+}
+
+void Any::serialize(BinaryOutput& b) const {
+ TextOutput::Settings s;
+ s.wordWrap = TextOutput::Settings::WRAP_NONE;
+ b.writeInt32(1);
+ b.writeString32(unparse(s));
+}
+
+
+void Any::deserialize(BinaryInput& b) {
+ const int version = b.readInt32();
+ alwaysAssertM(version == 1, "Wrong Any serialization version");
+ _parse(b.readString32());
+}
+
+
+std::string Any::resolveStringAsFilename(bool errorIfNotFound) const {
verifyType(STRING);
- std::string f = FileSystem::resolve(string(), sourceDirectory());
+ if ((string().length() > 0) && (string()[0] == '<') && (string()[string().length() - 1] == '>')) {
+ return string();
+ }
+
+ const std::string& f = FileSystem::resolve(string(), sourceDirectory());
if (FileSystem::exists(f)) {
return f;
} else {
- const std::string& s = System::findDataFile(string(), false);
+ const std::string& s = System::findDataFile(string(), errorIfNotFound);
if (s.empty()) {
return string();
} else {
@@ -37,6 +65,47 @@ std::string Any::resolveStringAsFilename() const {
}
}
+void Any::become(const Type& t) {
+ if ((t == ARRAY) || (t == TABLE)) {
+ debugAssert(m_type == EMPTY_CONTAINER);
+ m_type = t;
+ m_data->type = m_type;
+ if(t == ARRAY) {
+ m_data->value.a = new AnyArray();
+ } else {
+ m_data->value.t = new AnyTable();
+ }
+ }
+}
+
+
+void Any::remove(const std::string& key) {
+ verifyType(TABLE);
+ ensureMutable();
+ m_data->value.t->remove(key);
+}
+
+
+void Any::remove(int i) {
+ verifyType(ARRAY);
+ ensureMutable();
+ m_data->value.a->remove(i);
+}
+
+
+Any Any::fromFile(const std::string& filename) {
+ Any a;
+ a.load(filename);
+ return a;
+}
+
+
+void Any::loadIfExists(const std::string& filename) {
+ if (FileSystem::exists(filename)) {
+ load(filename);
+ }
+}
+
bool Any::nameBeginsWith(const std::string& s) const {
return nameBeginsWith(s.c_str());
@@ -73,7 +142,7 @@ bool Any::nameBeginsWith(const char* s) const {
bool Any::nameEquals(const char* s) const {
verifyType(Any::ARRAY, Any::TABLE);
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
return stricmp(name().c_str(), s) == 0;
#else
return strcasecmp(name().c_str(), s) == 0;
@@ -86,16 +155,11 @@ void Any::beforeRead() const {
if (isPlaceholder()) {
// Tried to read from a placeholder--throw an exception as if
// the original operator[] had failed.
- KeyNotFound e;
alwaysAssertM(m_data, "Corrupt placeholder");
+ KeyNotFound e(m_data);
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
e.key = m_placeholderName;
- e.message =
- "This exception may have been thrown later than "
- "the actual operator[] invocation.";
+ e.message = "Key \"" + m_placeholderName + "\" not found in operator[] lookup.";
throw e;
}
@@ -105,13 +169,18 @@ void Any::beforeRead() const {
Any::Data* Any::Data::create(const Data* d) {
Data* p = create(d->type);
- p->comment = d->comment;
- p->name = d->name;
+ p->includeLine = d->includeLine;
+ p->bracket = d->bracket;
+ p->separator = d->separator;
+ p->comment = d->comment;
+ p->name = d->name;
+ p->source = d->source;
switch (d->type) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
+ case EMPTY_CONTAINER:
// No clone needed
break;
@@ -134,11 +203,11 @@ Any::Data* Any::Data::create(const Data* d) {
}
-Any::Data* Any::Data::create(Any::Type t) {
+Any::Data* Any::Data::create(Any::Type t, const char* b, char sep) {
size_t s = sizeof(Data);
switch (t) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
// No extra space needed
@@ -148,23 +217,38 @@ Any::Data* Any::Data::create(Any::Type t) {
s += sizeof(std::string);
break;
+ case EMPTY_CONTAINER:
+ // We need to allocate space for the worst-case
+ s += max(sizeof(AnyArray), sizeof(AnyTable));
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = PAREN; }
+ if (sep == '\0') { sep = ','; }
+ break;
+
case ARRAY:
s += sizeof(AnyArray);
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = PAREN; }
+ if (sep == '\0') { sep = ','; }
break;
case TABLE:
s += sizeof(AnyTable);
+ // If no separator and brackets were provided, substitute defaults
+ if (b == NULL) { b = BRACE; }
+ if (sep == '\0') { sep = ';'; }
break;
}
// Allocate the data object
- Data* p = new (MemoryManager::create()->alloc(s)) Data(t);
+ Data* p = new (MemoryManager::create()->alloc(s)) Data(t, b, sep);
- // Create the (empyt) value object at the end of the Data object
+ // Create the (empty) value object at the end of the Data object
switch (t) {
- case NONE:
+ case NIL:
case BOOLEAN:
case NUMBER:
+ case EMPTY_CONTAINER:
// No value
break;
@@ -179,7 +263,9 @@ Any::Data* Any::Data::create(Any::Type t) {
case TABLE:
p->value.t = new (p + 1) AnyTable();
break;
- }
+ }
+
+ if (isContainerType(p->type)) debugAssert(p->separator != '\0');
return p;
}
@@ -227,7 +313,10 @@ Any::Data::~Data() {
bool Any::containsKey(const std::string& x) const {
beforeRead();
verifyType(TABLE);
-
+ if (size() == 0) {
+ //catches the case of an empty container, where value.t is null
+ return false;
+ }
Any* a = m_data->value.t->getPointer(x);
// Don't return true for placeholder objects
@@ -255,16 +344,16 @@ void Any::ensureMutable() {
}
-Any::Any() : m_type(NONE), m_data(NULL) {
+Any::Any() : m_type(NIL), m_data(NULL) {
}
-Any::Any(TextInput& t) : m_type(NONE), m_data(NULL) {
+Any::Any(TextInput& t) : m_type(NIL), m_data(NULL) {
deserialize(t);
}
-Any::Any(const Any& x) : m_type(NONE), m_data(NULL) {
+Any::Any(const Any& x) : m_type(NIL), m_data(NULL) {
x.beforeRead();
*this = x;
}
@@ -274,15 +363,15 @@ Any::Any(double x) : m_type(NUMBER), m_simpleValue(x), m_data(NULL) {
}
-#ifdef G3D_32BIT
-Any::Any(int64 x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+Any::Any(float x) : m_type(NUMBER), m_simpleValue(double(x)), m_data(NULL) {
}
-#endif // G3D_32BIT
-Any::Any(long x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+Any::Any(char x) : m_type(NUMBER), m_simpleValue(double(x)), m_data(NULL) {
}
+Any::Any(long x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
+}
Any::Any(int x) : m_type(NUMBER), m_simpleValue((double)x), m_data(NULL) {
}
@@ -303,7 +392,7 @@ Any::Any(const std::string& s) : m_type(STRING), m_data(Data::create(STRING)) {
Any::Any(const char* s) : m_type(STRING), m_data(NULL) {
if (s == NULL) {
- m_type = NONE;
+ m_type = NIL;
} else {
ensureData();
*(m_data->value.s) = s;
@@ -311,13 +400,43 @@ Any::Any(const char* s) : m_type(STRING), m_data(NULL) {
}
-Any::Any(Type t, const std::string& name) : m_type(t), m_data(NULL) {
- alwaysAssertM(t == ARRAY || t == TABLE, "Can only create ARRAY or TABLE from Type enum.");
+
+
+Any::Any(Type t, const std::string& name, const std::string& brackets, char separator) : m_type(t), m_data(NULL) {
+ alwaysAssertM(isContainerType(t), "Can only create ARRAY or TABLE from Type enum.");
ensureData();
if (name != "") {
m_data->name = name;
}
+
+ if (brackets == "") {
+ if (t == ARRAY) {
+ m_data->bracket = PAREN;
+ } else {
+ m_data->bracket = BRACE;
+ }
+ } else if (brackets == PAREN) {
+ m_data->bracket = PAREN;
+ } else if (brackets == BRACE) {
+ m_data->bracket = BRACE;
+ } else if (brackets == BRACKET) {
+ m_data->bracket = BRACKET;
+ } else {
+ alwaysAssertM(false, std::string("illegal brackets: ") + brackets);
+ }
+
+ if (separator == '\0') {
+ if (t == ARRAY) {
+ m_data->separator = ',';
+ } else {
+ m_data->separator = ';';
+ }
+ } else if (separator == ',' || separator == ';') {
+ m_data->separator = separator;
+ } else {
+ alwaysAssertM(false, std::string("illegal separator: ") + separator);
+ }
}
@@ -329,10 +448,17 @@ Any::~Any() {
void Any::beforeWrite() {
if (isPlaceholder()) {
// This is no longer a placeholder
- m_placeholderName = "";
+ m_placeholderName.clear();
+ }
+
+ if (m_data && ! m_data->includeLine.empty()) {
+ // Forget where this Any was included from...it no
+ // longer matches the contents there.
+ m_data->includeLine = "";
}
}
+
Any& Any::operator=(const Any& x) {
x.beforeRead();
@@ -356,48 +482,20 @@ Any& Any::operator=(const Any& x) {
}
-Any& Any::operator=(double x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(int x) {
- return (*this = Any(x));
-}
-
-
-Any& Any::operator=(bool x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const std::string& x) {
- *this = Any(x);
- return *this;
-}
-
-
-Any& Any::operator=(const char* x) {
- *this = Any(x);
- return *this;
-}
-
-
Any& Any::operator=(Type t) {
switch (t) {
- case NONE:
+ case NIL:
*this = Any();
break;
- case TABLE:
- case ARRAY:
+ case TABLE: // All 3 cases intentionally fall through
+ case ARRAY:
+ case EMPTY_CONTAINER:
*this = Any(t);
break;
default:
- alwaysAssertM(false, "Can only assign NONE, TABLE, or ARRAY Type enum.");
+ alwaysAssertM(false, "Can only assign NIL, TABLE, or ARRAY Type enum.");
}
return *this;
@@ -429,18 +527,23 @@ void Any::setComment(const std::string& c) {
}
-bool Any::isNone() const {
+bool Any::isNil() const {
beforeRead();
- return (m_type == NONE);
+ return (m_type == NIL);
}
-
double Any::number() const {
beforeRead();
verifyType(NUMBER);
return m_simpleValue.n;
}
+float Any::floatValue() const {
+ beforeRead();
+ verifyType(NUMBER);
+ return (float)m_simpleValue.n;
+}
+
const std::string& Any::string() const {
beforeRead();
@@ -479,14 +582,14 @@ int Any::size() const {
verifyType(ARRAY, TABLE);
switch (m_type) {
case TABLE:
- return m_data->value.t->size();
+ return (int)m_data->value.t->size();
case ARRAY:
return m_data->value.a->size();
- default:;
+ default:
return 0;
- } // switch (m_type)
+ }
}
@@ -500,6 +603,9 @@ void Any::resize(int n) {
beforeRead();
alwaysAssertM(n >= 0, "Cannot resize less than 0.");
verifyType(ARRAY);
+ if (type() == EMPTY_CONTAINER) {
+ become(ARRAY);
+ }
m_data->value.a->resize(n);
}
@@ -515,7 +621,6 @@ void Any::clear() {
case TABLE:
m_data->value.t->clear();
break;
-
default:;
}
}
@@ -526,6 +631,9 @@ const Any& Any::operator[](int i) const {
verifyType(ARRAY);
debugAssert(m_data != NULL);
Array<Any>& array = *(m_data->value.a);
+ if (i < 0 || i >= array.size()) {
+ throw IndexOutOfBounds(m_data, i, array.size());
+ }
return array[i];
}
@@ -541,9 +649,13 @@ Any& Any::next() {
Any& Any::operator[](int i) {
beforeRead();
+ ensureMutable();
verifyType(ARRAY);
debugAssert(m_data != NULL);
Array<Any>& array = *(m_data->value.a);
+ if (i < 0 || i >= array.size()) {
+ throw IndexOutOfBounds(m_data, i, array.size());
+ }
return array[i];
}
@@ -556,22 +668,25 @@ const Array<Any>& Any::array() const {
}
-void Any::append(const Any& x0) {
+void Any::_append(const Any& x0) {
beforeRead();
verifyType(ARRAY);
debugAssert(m_data != NULL);
+ if (type() == EMPTY_CONTAINER) {
+ become(ARRAY);
+ }
m_data->value.a->append(x0);
}
-void Any::append(const Any& x0, const Any& x1) {
+void Any::_append(const Any& x0, const Any& x1) {
beforeRead();
append(x0);
append(x1);
}
-void Any::append(const Any& x0, const Any& x1, const Any& x2) {
+void Any::_append(const Any& x0, const Any& x1, const Any& x2) {
beforeRead();
append(x0);
append(x1);
@@ -579,7 +694,7 @@ void Any::append(const Any& x0, const Any& x1, const Any& x2) {
}
-void Any::append(const Any& x0, const Any& x1, const Any& x2, const Any& x3) {
+void Any::_append(const Any& x0, const Any& x1, const Any& x2, const Any& x3) {
beforeRead();
append(x0);
append(x1);
@@ -592,6 +707,12 @@ const Table<std::string, Any>& Any::table() const {
beforeRead();
verifyType(TABLE);
debugAssert(m_data != NULL);
+
+ if (type() == Any::EMPTY_CONTAINER) {
+ // if empty, m_data->value.t will not be initialized as it is unknown whether this is supposed to be an array or a table
+ static const Table<std::string, Any> emptyTable;
+ return emptyTable;
+ }
return *(m_data->value.t);
}
@@ -603,13 +724,9 @@ const Any& Any::operator[](const std::string& x) const {
const Table<std::string, Any>& table = *(m_data->value.t);
Any* value = table.getPointer(x);
if (value == NULL) {
- KeyNotFound e;
- if (m_data) {
- e.filename = m_data->source.filename;
- e.line = m_data->source.line;
- e.character = m_data->source.character;
- }
+ KeyNotFound e(m_data);
e.key = x;
+ e.message = "Key not found in operator[] lookup.";
throw e;
}
return *value;
@@ -618,6 +735,7 @@ const Any& Any::operator[](const std::string& x) const {
Any& Any::operator[](const std::string& key) {
beforeRead();
+ ensureMutable();
verifyType(TABLE);
bool created = false;
@@ -637,17 +755,20 @@ Any& Any::operator[](const std::string& key) {
}
-void Any::set(const std::string& k, const Any& v) {
+void Any::_set(const std::string& k, const Any& v) {
beforeRead();
v.beforeRead();
verifyType(TABLE);
debugAssert(m_data != NULL);
+ if ( type() == EMPTY_CONTAINER) {
+ become(TABLE);
+ }
Table<std::string, Any>& table = *(m_data->value.t);
table.set(k, v);
}
-const Any& Any::get(const std::string& x, const Any& defaultVal) const {
+Any Any::_get(const std::string& x, const Any& defaultVal) const {
beforeRead();
defaultVal.beforeRead();
try {
@@ -661,12 +782,13 @@ const Any& Any::get(const std::string& x, const Any& defaultVal) const {
bool Any::operator==(const Any& x) const {
beforeRead();
x.beforeRead();
+
if (m_type != x.m_type) {
return false;
}
switch (m_type) {
- case NONE:
+ case NIL:
return true;
case BOOLEAN:
@@ -687,14 +809,17 @@ bool Any::operator==(const Any& x) const {
if (m_data->name != x.m_data->name) {
return false;
}
- Table<std::string, Any>& cmptable = *( m_data->value.t);
- Table<std::string, Any>& xcmptable = *(x.m_data->value.t);
- for (Table<std::string,Any>::Iterator it1 = cmptable.begin(), it2 = xcmptable.begin();
- it1 != cmptable.end() && it2 != xcmptable.end();
- ++it1, ++it2) {
- if (*it1 != *it2) {
+ const Table<std::string, Any>& table1 = table();
+ const Table<std::string, Any>& table2 = x.table();
+ for (Table<std::string, Any>::Iterator it = table1.begin(); it.isValid(); ++it) {
+ const Any* p2 = table2.getPointer(it->key);
+ if (p2 == NULL) {
+ // Key not found
+ return false;
+ } else if (*p2 != it->value) {
+ // Different value
return false;
- }
+ }
}
return true;
}
@@ -718,19 +843,19 @@ bool Any::operator==(const Any& x) const {
}
return true;
}
-
+
+ case EMPTY_CONTAINER:
+ return true;
default:
alwaysAssertM(false, "Unknown type.");
return false;
- } // switch (m_type)
+ }
}
bool Any::operator!=(const Any& x) const {
- beforeRead();
- x.beforeRead();
- return !operator==(x);
+ return ! operator==(x);
}
@@ -740,21 +865,35 @@ static void getDeserializeSettings(TextInput::Settings& settings) {
settings.otherLineComments = false;
settings.generateCommentTokens = true;
settings.singleQuotedStrings = false;
- settings.msvcFloatSpecials = false;
+ settings.msvcFloatSpecials = true;
settings.caseSensitive = false;
}
-std::string Any::unparse() const {
+std::string Any::unparseJSON(const TextOutput::Settings& settings, bool allowCoercion) const {
+ beforeRead();
+ TextOutput to(settings);
+ serialize(to, true, allowCoercion);
+ return to.commitString();
+}
+
+
+std::string Any::unparse(const TextOutput::Settings& settings) const {
beforeRead();
- TextOutput::Settings settings;
TextOutput to(settings);
serialize(to);
return to.commitString();
}
-void Any::parse(const std::string& src) {
+Any Any::parse(const std::string& src) {
+ Any a;
+ a._parse(src);
+ return a;
+}
+
+
+void Any::_parse(const std::string& src) {
beforeRead();
TextInput::Settings settings;
getDeserializeSettings(settings);
@@ -814,16 +953,41 @@ static bool needsQuotes(const std::string& s) {
}
-// TODO: if the output will fit on one line, compress tables and arrays into a single line
-void Any::serialize(TextOutput& to) const {
+void Any::serialize(TextOutput& to, bool json, bool coerce) const {
beforeRead();
+
+ if (m_data && ! m_data->includeLine.empty()) {
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+
+ // Silently fall through
+ } else {
+ // This value came from a #include...preserve it. This includes the comment
+ // if any.
+ to.printf("%s", m_data->includeLine.c_str());
+ return;
+ }
+ }
+
if (m_data && ! m_data->comment.empty()) {
- to.printf("\n/* %s */\n", m_data->comment.c_str());
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+ } else {
+ to.printf("\n/* %s */\n", m_data->comment.c_str());
+ }
}
switch (m_type) {
- case NONE:
- to.writeSymbol("NONE");
+ case NIL:
+ if (json) {
+ to.writeSymbol("null");
+ } else {
+ to.writeSymbol("NIL");
+ }
break;
case BOOLEAN:
@@ -831,7 +995,24 @@ void Any::serialize(TextOutput& to) const {
break;
case NUMBER:
- to.writeNumber(m_simpleValue.n);
+ if (json) {
+ // Specials have no legal syntax in JSON, so insert values that will parse
+ // to something close to what we want (there is no good solution for NaN, unfortunately)
+ if (m_simpleValue.n == inf()) {
+ to.writeSymbol("1e10000");
+ } else if (m_simpleValue.n == -inf()) {
+ to.writeSymbol("-1e10000");
+ } else if (isNaN(m_simpleValue.n)) {
+ if (! coerce) {
+ throw "There is no way to represent NaN in JSON";
+ }
+ to.writeSymbol("null");
+ } else {
+ to.writeNumber(m_simpleValue.n);
+ }
+ } else {
+ to.writeNumber(m_simpleValue.n);
+ }
break;
case STRING:
@@ -841,14 +1022,26 @@ void Any::serialize(TextOutput& to) const {
case TABLE: {
debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
if (! m_data->name.empty()) {
- if (needsQuotes(m_data->name)) {
- to.writeString(m_data->name);
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
} else {
- to.writeSymbol(m_data->name);
+ if (needsQuotes(m_data->name)) {
+ to.writeString(m_data->name);
+ } else {
+ to.writeSymbol(m_data->name);
+ }
}
}
- to.writeSymbol("{");
+ if (json) {
+ to.writeSymbol("{");
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
to.writeNewline();
to.pushIndent();
AnyTable& table = *(m_data->value.t);
@@ -858,56 +1051,134 @@ void Any::serialize(TextOutput& to) const {
for (int i = 0; i < keys.size(); ++i) {
- to.writeSymbol(keys[i]);
- to.writeSymbol("=");
- table[keys[i]].serialize(to);
+ int prevLine = to.line();
+ if (needsQuotes(keys[i]) || json) {
+ to.writeString(keys[i]);
+ } else {
+ to.writeSymbol(keys[i]);
+ }
- if (i < keys.size() - 1) {
- to.writeSymbol(",");
+ if (json) {
+ to.writeSymbol(":");
+ } else {
+ to.writeSymbol("=");
+ }
+ table[keys[i]].serialize(to, json, coerce);
+
+ to.deleteSpace();
+ if (json) {
+ // Don't put a separator after the last
+ if (i != keys.size() - 1) {
+ to.writeSymbol(",");
+ }
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+
+ // Skip an extra line between table entries that are longer than a line
+ if (prevLine != to.line()) {
+ to.writeNewline();
}
- to.writeNewline();
- // Skip a line between table entries
to.writeNewline();
}
to.popIndent();
- to.writeSymbol("}");
+ to.writeSymbol(m_data->bracket[1]);
break;
}
case ARRAY: {
debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
if (! m_data->name.empty()) {
- // For arrays, leave no trailing space between the name and the paren
- to.writeSymbol(format("%s(", m_data->name.c_str()));
+ if (json) {
+ if (! coerce) {
+ throw "Could not coerce to JSON";
+ }
+ to.writeSymbol("[");
+ } else {
+ // For arrays, leave no trailing space between the name and the paren
+ to.printf("%s%c", m_data->name.c_str(), m_data->bracket[0]);
+ }
} else {
- to.writeSymbol("(");
+ if (json) {
+ to.writeSymbol("[");
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
}
- to.writeNewline();
+ const Array<Any>& array = *(m_data->value.a);
+ const bool longForm = (array.size() > 0) && ((array[0].type() == ARRAY) || (array[0].type() == TABLE));
+
+ if (longForm) {
+ to.writeNewline();
+ }
+
to.pushIndent();
- Array<Any>& array = *(m_data->value.a);
for (int ii = 0; ii < size(); ++ii) {
- array[ii].serialize(to);
+ array[ii].serialize(to, json, coerce);
if (ii < size() - 1) {
- to.writeSymbol(",");
- to.writeNewline();
+ to.deleteSpace();
+ if (longForm) {
+ // Probably a long-form array
+ if (json) {
+ to.writeSymbol(",");
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+ to.writeNewline();
+ } else {
+ // Probably a short-form array
+ if (json) {
+ to.writeSymbol(",");
+ } else {
+ to.writeSymbol(m_data->separator);
+ }
+ }
}
// Put the close paren on an array right behind the last element
}
to.popIndent();
- to.writeSymbol(")");
+ if (json) {
+ to.writeSymbol("]");
+ } else {
+ to.writeSymbol(m_data->bracket[1]);
+ }
+ break;
+ }
+
+ case EMPTY_CONTAINER: {
+ debugAssert(m_data != NULL);
+ debugAssert(m_data->separator != '\0');
+
+ if (json) {
+ if (! coerce) {
+ throw "Cannot strictly convert the ambiguous Any empty container to JSON";
+ }
+ to.writeSymbols("[", "]");
+ } else {
+ if (! m_data->name.empty()) {
+ // Leave no trailing space between the name and the paren
+ to.printf("%s%c", m_data->name.c_str(), m_data->bracket[0]);
+ } else {
+ to.writeSymbol(m_data->bracket[0]);
+ }
+ to.writeSymbol(m_data->bracket[1]);
+ }
break;
}
}
+
}
void Any::deserializeComment(TextInput& ti, Token& token, std::string& comment) {
// Parse comments
while (token.type() == Token::COMMENT) {
- comment += trimWhitespace(token.string()) + "\n";
+ comment += trimWhitespace(token.string());
// Allow comments to contain newlines.
do {
@@ -919,6 +1190,7 @@ void Any::deserializeComment(TextInput& ti, Token& token, std::string& comment)
comment = trimWhitespace(comment);
}
+
/** True if \a c is an open paren of some form */
static bool isOpen(const char c) {
return c == '(' || c == '[' || c == '{';
@@ -961,7 +1233,7 @@ void Any::deserialize(TextInput& ti) {
void Any::deserialize(TextInput& ti, Token& token) {
// Deallocate old data
dropReference();
- m_type = NONE;
+ m_type = NIL;
m_simpleValue.b = false;
// Skip leading newlines
@@ -1009,7 +1281,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
break;
case Token::SYMBOL:
- // Pragma, Named Array, Named Table, Array, Table, or NONE
+ // Pragma, Named Array, Named Table, Array, Table, or NIL
if (token.string() == "#") {
// Pragma
@@ -1022,14 +1294,16 @@ void Any::deserialize(TextInput& ti, Token& token) {
}
ti.readSymbol("(");
+ // The string typed into the file, which may be relative
const std::string& includeName = ti.readString();
// Find the include file
- const std::string& myPath = filenamePath(ti.filename());
- std::string t = pathConcat(myPath, includeName);
+ const std::string& myPath = FilePath::parent(ti.filename());
+
+ std::string t = FileSystem::resolve(includeName, myPath);
if (! FileSystem::exists(t)) {
- // Try and find it, starting with cwd
+ // Try and find the path, starting with the cwd
t = System::findDataFile(includeName);
}
@@ -1038,20 +1312,29 @@ void Any::deserialize(TextInput& ti, Token& token) {
// Update the source information
ensureData();
- m_data->source.filename +=
+ if (! comment.empty()) {
+ m_data->includeLine = format("\n/* %s */\n", comment.c_str());
+ }
+ m_data->includeLine += format("#include(\"%s\")", includeName.c_str());
+ m_data->source.filename +=
format(" [included from %s:%d(%d)]", ti.filename().c_str(), token.line(), token.character());
ti.readSymbol(")");
- } else if (toUpper(token.string()) == "NONE") {
- // Nothing left to do; we initialized to NONE originally
+ } else if (toUpper(token.string()) == "NIL" || token.string() == "None") {
+ // Nothing left to do; we initialized to NIL originally
+ ensureData();
+ m_data->source.set(ti, token);
+ } else if (isValidIdentifier(token.string()) && !isOpen(ti.peek().string()[0]) && ti.peek().string() != "::") {
+ // Valid unquoted string
+ m_type = STRING;
ensureData();
+ *(m_data->value.s) = token.string();
m_data->source.set(ti, token);
} else {
// Array or Table
// Parse the name
-
// s must have at least one element or this would not have
// been parsed as a symbol
std::string name;
@@ -1074,7 +1357,7 @@ void Any::deserialize(TextInput& ti, Token& token) {
m_data->name = name;
}
needRead = false;
- } // if NONE
+ } // if NIL
break;
default:
@@ -1107,10 +1390,11 @@ static bool isSeparator(char c) {
}
-void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
+void Any::readUntilSeparatorOrClose(TextInput& ti, Token& token) {
bool atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
- bool atComma = isSeparator(token.string()[0]);
- while (! (atClose || atComma)) {
+ bool atSeparator = isSeparator(token.string()[0]);
+
+ while (! (atClose || atSeparator)) {
switch (token.type()) {
case Token::NEWLINE:
case Token::COMMENT:
@@ -1123,28 +1407,85 @@ void Any::readUntilCommaOrClose(TextInput& ti, Token& token) {
"Expected a comma or close paren");
}
- // Update checks
- atComma = isSeparator(token.string()[0]);
+ // Update checks
+ atSeparator = isSeparator(token.string()[0]);
atClose = (token.type() == Token::SYMBOL) && isClose(token.string()[0]);
}
}
+/**
+ Determines the type [TABLE, ARRAY, or EMPTY_CONTAINER] from the given TextInput
+ TextInput is the same at the end as it was beofr
+*/
+static Any::Type findType(TextInput& ti, const char closeSymbol) {
+ Any::Type type = Any::NIL;
+ std::vector<Token> tokens;
+ // consumes the open symbol
+ Token token = ti.read();
+ tokens.push_back(token);
+
+ bool hasAnElement = false;
+ while (type == Any::NIL) {
+ if (token.type() == Token::COMMENT) {
+ // consumes tokens and prepares to push them back onto the TextInput
+ token = ti.read();
+ tokens.push_back(token);
+ } else if ((token.type() == Token::SYMBOL) && ((token.string() == "=") || (token.string() == ":"))) {
+ // an '=' indicates a key = value pairing, and thus a table
+ type = Any::TABLE;
+ } else if (hasAnElement) {
+ // any non-comment, non-'=' token after any element indicates an array
+ type = Any::ARRAY;
+ } else if ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol)) {
+ // catches no previous element and a closing symbol (e.g [])
+ type = Any::EMPTY_CONTAINER;
+ } else {
+ // consumes elements, indicating one has been seen, and prepares to push them back onto TextInput
+ hasAnElement = true;
+ token = ti.read();
+ tokens.push_back(token);
+ }
+ }
+ // pushes everything back to the TextInput
+ while (!tokens.empty()) {
+ token = tokens.back();
+ ti.push(token);
+ tokens.pop_back();
+ }
+ return type;
+}
+
void Any::deserializeBody(TextInput& ti, Token& token) {
- char closeSymbol = '}';
+ char closeSymbol = '\0';
m_type = TABLE;
const char c = token.string()[0];
-
- if (c != '{') {
- m_type = ARRAY;
- // Chose the appropriate close symbol
- closeSymbol = (c == '(') ? ')' : ']';
+
+ // Chose the appropriate close symbol based on the open symbol
+ const char* bracket;
+ if (c == '(') {
+ bracket = PAREN;
+ } else if (c == '[') {
+ bracket = BRACKET;
+ } else if (c == '{') {
+ bracket = BRACE;
+ } else {
+ debugAssertM(false, "Illegal bracket type");
+ bracket = PAREN;
}
+ closeSymbol = bracket[1];
+
+ // We must set the type before we allocate m_data in ensureData().
+ m_type = findType(ti, closeSymbol);
// Allocate the underlying data structure
ensureData();
m_data->source.set(ti, token);
+ m_data->bracket = bracket;
+
+ debugAssert(m_data->type == m_type);
+ debugAssert(m_data->separator != '\0');
// Consume the open token
token = ti.read();
@@ -1157,12 +1498,12 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
deserializeComment(ti, token, comment);
if ((token.type() == Token::SYMBOL) && (token.string()[0] == closeSymbol)) {
- // We're done; this catches the case where the array is empty
+ // We're done; this catches the case where the container is empty
break;
}
// Pointer the value being read
- Any a = NULL;
+ Any a;
std::string key;
if (m_type == TABLE) {
@@ -1175,8 +1516,8 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
// Consume everything up to the = sign, returning the "=" sign.
token = ti.readSignificant();
- if ((token.type() != Token::SYMBOL) || (token.string() != "=")) {
- throw ParseError(ti.filename(), token.line(), token.character(), "Expected =");
+ if ((token.type() != Token::SYMBOL) || ((token.string() != "=") && token.string() != ":")) {
+ throw ParseError(ti.filename(), token.line(), token.character(), "Expected = or :");
} else {
// Read the next token, which is the value (don't consume comments--we want the value pointed to by a to get those).
token = ti.read();
@@ -1196,12 +1537,16 @@ void Any::deserializeBody(TextInput& ti, Token& token) {
append(a);
}
- // Read until the comma or close paren, discarding trailing comments and newlines
- readUntilCommaOrClose(ti, token);
+ // Read until the separator or close paren, discarding trailing comments and newlines
+ readUntilSeparatorOrClose(ti, token);
- // Consume the comma
- if (isSeparator(token.string()[0])) {
+ char s = token.string()[0];
+
+ // Consume the separator
+ if (isSeparator(s)) {
token = ti.read();
+ m_data->separator = s;
+ debugAssert(m_data->separator != '\0');
}
}
@@ -1216,6 +1561,12 @@ Any::operator int() const {
}
+Any::operator uint32() const {
+ beforeRead();
+ return uint32(number() + 0.5);
+}
+
+
Any::operator float() const {
beforeRead();
return float(number());
@@ -1258,7 +1609,6 @@ std::string Any::sourceDirectory() const {
}
}
-
void Any::verify(bool value, const std::string& message) const {
beforeRead();
if (! value) {
@@ -1286,21 +1636,109 @@ void Any::verify(bool value, const std::string& message) const {
void Any::verifyName(const std::string& n) const {
beforeRead();
- verify(beginsWith(toUpper(name()), toUpper(n)), "Name must begin with " + n);
+ verify(name() == n, "Name must be " + n);
}
void Any::verifyName(const std::string& n, const std::string& m) const {
beforeRead();
- const std::string& x = toUpper(name());
- verify(beginsWith(x, toUpper(n)) ||
- beginsWith(x, toUpper(m)), "Name must begin with " + n + " or " + m);
+ const std::string& x = name();
+ verify(x == n ||
+ x == m, "Name must be " + n + " or " + m);
+}
+
+
+void Any::verifyName(const std::string& n, const std::string& m, const std::string& p) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(x == n ||
+ x == m ||
+ x == p, "Name must be " + n + ", " + m + ", or " + p);
+}
+
+
+void Any::verifyName(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(x == n ||
+ x == m ||
+ x == p ||
+ x == q, "Name must be " + n + ", " + m + ", " + p + ", or " + q);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n) const {
+ beforeRead();
+ verify(beginsWith(name(), n), "Name must begin with " + n);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m), "Name must be " + n + " or " + m);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p), "Name must be " + n + ", " + m + ", or " + p);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q), "Name must be " + n + ", " + m + ", " + p + ", or " + q);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r) ||
+ beginsWith(x, s), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r + ", or " + s);
+}
+
+
+void Any::verifyNameBeginsWith(const std::string& n, const std::string& m, const std::string& p, const std::string& q, const std::string& r, const std::string& s, const std::string& t) const {
+ beforeRead();
+ const std::string& x = name();
+ verify(beginsWith(x, n) ||
+ beginsWith(x, m) ||
+ beginsWith(x, p) ||
+ beginsWith(x, q) ||
+ beginsWith(x, r) ||
+ beginsWith(x, s) ||
+ beginsWith(x, t), "Name must be " + n + ", " + m + ", " + p + ", or " + q + ", or " + r + ", or " + s + ", or " + t);
}
void Any::verifyType(Type t) const {
beforeRead();
- if (type() != t) {
+ if ((type() != t) && ! ((type() == EMPTY_CONTAINER) && isContainerType(t))) {
verify(false, "Must have type " + toString(t));
}
}
@@ -1308,7 +1746,8 @@ void Any::verifyType(Type t) const {
void Any::verifyType(Type t0, Type t1) const {
beforeRead();
- if (type() != t0 && type() != t1) {
+ if ((type() != t0 && !((type() == EMPTY_CONTAINER) && isContainerType(t0))) &&
+ (type() != t1 && !((type() == EMPTY_CONTAINER) && isContainerType(t1)))) {
verify(false, "Must have type " + toString(t0) + " or " + toString(t1));
}
}
@@ -1334,7 +1773,7 @@ void Any::verifySize(int s) const {
std::string Any::toString(Type t) {
switch(t) {
- case NONE: return "NONE";
+ case NIL: return "NIL";
case BOOLEAN: return "BOOLEAN";
case NUMBER: return "NUMBER";
case STRING: return "STRING";
diff --git a/dep/g3dlite/source/AnyTableReader.cpp b/dep/g3dlite/source/AnyTableReader.cpp
new file mode 100644
index 00000000000..7fff1983e46
--- /dev/null
+++ b/dep/g3dlite/source/AnyTableReader.cpp
@@ -0,0 +1,50 @@
+#include "G3D/Any.h"
+
+namespace G3D {
+
+/** Verifies that \a is a TABLE with the given \a name. */
+AnyTableReader::AnyTableReader(const std::string& name, const Any& a) : m_any(a) {
+ try {
+ m_any.verifyType(Any::TABLE);
+ m_any.verifyName(name);
+ } catch (const ParseError& e) {
+ // If an exception is thrown, the destructors will not be
+ // invoked automatically.
+ m_any.~Any();
+ m_alreadyRead.~Set();
+ throw e;
+ }
+}
+
+
+AnyTableReader::AnyTableReader(const Any& a) : m_any(a) {
+ try {
+ m_any.verifyType(Any::TABLE);
+ } catch (const ParseError& e) {
+ // If an exception is thrown, the destructors will not be
+ // invoked automatically.
+ m_any.~Any();
+ m_alreadyRead.~Set();
+ throw e;
+ }
+}
+
+
+void AnyTableReader::verifyDone() const {
+ if (hasMore()) {
+ // Some entries were unread. Find them.
+ const Table<std::string, Any>& table = m_any.table();
+
+ for (Table<std::string, Any>::Iterator it = table.begin();
+ it.hasMore();
+ ++it) {
+
+ if (containsUnread(it->key)) {
+ it->value.verify(false, std::string("Unread Any table key \"") + it->key + "\"");
+ }
+ }
+ }
+}
+
+
+} // namespace G3D
diff --git a/dep/g3dlite/source/AnyVal.cpp b/dep/g3dlite/source/AnyVal.cpp
deleted file mode 100644
index 7b98486523a..00000000000
--- a/dep/g3dlite/source/AnyVal.cpp
+++ /dev/null
@@ -1,1379 +0,0 @@
-/**
- @file AnyVal.cpp
- @author Morgan McGuire
- @maintainer Morgan McGuire
- @created 2006-06-11
- @edited 2008-07-14
- */
-
-#include "G3D/AnyVal.h"
-#include "G3D/Array.h"
-#include "G3D/stringutils.h"
-#include "G3D/Table.h"
-#include "G3D/Vector2.h"
-#include "G3D/Vector3.h"
-#include "G3D/Vector4.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/Rect2D.h"
-#include "G3D/AABox.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Quat.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-AnyVal AnyVal::fromFile(const std::string& filename) {
- TextInput t(filename);
- return AnyVal(t);
-}
-
-
-void AnyVal::load(const std::string& filename) {
- *this = fromFile(filename);
-}
-
-
-void AnyVal::save(const std::string& filename) const {
- TextOutput t(filename);
- serialize(t);
- t.commit();
-}
-
-
-AnyVal::AnyVal() : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
-}
-
-
-AnyVal::AnyVal(bool b) : m_type(BOOLEAN), m_value(new bool(b)), m_referenceCount(NULL) {
-}
-
-
-AnyVal::AnyVal(G3D::TextInput& t) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
- deserialize(t);
-}
-
-
-/*AnyVal::AnyVal(G3D::BinaryInput& b) {
- deserialize(b);
-}
-*/
-
-AnyVal::AnyVal(double v) : m_type(NUMBER), m_referenceCount(NULL) {
- m_value = new double(v);
-}
-
-
-AnyVal::AnyVal(int v) : m_type(NUMBER), m_referenceCount(NULL) {
- m_value = new double(v);
-}
-
-
-AnyVal::AnyVal(const Rect2D& v) : m_type(RECT2D), m_referenceCount(NULL) {
- m_value = new Rect2D(v);
-}
-
-
-AnyVal::AnyVal(const AABox& v) : m_type(AABOX), m_referenceCount(NULL) {
- m_value = new AABox(v);
-}
-
-
-AnyVal::AnyVal(const Vector2& v) : m_type(VECTOR2), m_referenceCount(NULL) {
- m_value = new Vector2(v);
-}
-
-
-AnyVal::AnyVal(const Vector3& v) : m_type(VECTOR3), m_referenceCount(NULL) {
- m_value = new Vector3(v);
-}
-
-
-AnyVal::AnyVal(const Vector4& v) : m_type(VECTOR4), m_referenceCount(NULL) {
- m_value = new Vector4(v);
-}
-
-
-AnyVal::AnyVal(const Color1& v) : m_type(COLOR1), m_referenceCount(NULL) {
- m_value = new Color1(v);
-}
-
-
-AnyVal::AnyVal(const Color3& v) : m_type(COLOR3), m_referenceCount(NULL) {
- m_value = new Color3(v);
-}
-
-
-AnyVal::AnyVal(const Color4& v) : m_type(COLOR4), m_referenceCount(NULL) {
- m_value = new Color4(v);
-}
-
-
-AnyVal::AnyVal(const std::string& v) : m_type(STRING), m_referenceCount(NULL) {
- m_value = new std::string(v);
-}
-
-
-AnyVal::AnyVal(const char* v) : m_type(STRING), m_referenceCount(NULL) {
- m_value = new std::string(v);
-}
-
-
-AnyVal::AnyVal(const Quat& v) : m_type(QUAT), m_referenceCount(NULL) {
- m_value = new Quat(v);
-}
-
-
-AnyVal::AnyVal(const CoordinateFrame& v) : m_type(COORDINATEFRAME), m_referenceCount(NULL) {
- m_value = new CoordinateFrame(v);
-}
-
-
-AnyVal::AnyVal(const Matrix2& v) : m_type(MATRIX2), m_referenceCount(NULL) {
- m_value = new Matrix2(v);
-}
-
-AnyVal::AnyVal(const Matrix3& v) : m_type(MATRIX3), m_referenceCount(NULL) {
- m_value = new Matrix3(v);
-}
-
-
-AnyVal::AnyVal(const Matrix4& v) : m_type(MATRIX4), m_referenceCount(NULL) {
- m_value = new Matrix4(v);
-}
-
-
-AnyVal::AnyVal(const AnyVal& c) : m_type(NIL), m_value(NULL), m_referenceCount(NULL) {
- *this = c;
-}
-
-
-AnyVal::AnyVal(Type arrayOrTable) : m_type(NIL), m_value(NULL), m_referenceCount(new int(1)) {
- // TODO: make AnyVal::createArray()
- switch (arrayOrTable) {
- case ARRAY:
- m_type = ARRAY;
- m_value = new Array<AnyVal>();
- break;
-
- case TABLE:
- m_type = TABLE;
- m_value = new Table<std::string, AnyVal>();
- break;
-
- default:
- debugAssertM(false, "Cannot construct AnyVal from constants except ARRAY or TABLE.");
- }
-}
-
-
-AnyVal::~AnyVal() {
- deleteValue();
-}
-
-
-void AnyVal::deleteValue() {
- if (m_referenceCount) {
- --(*m_referenceCount);
- if (*m_referenceCount <= 0) {
- delete m_referenceCount;
- m_referenceCount = NULL;
- // Pass through and delete the real object now
- } else {
- // Someone else is holding a reference, so we can't delete
- // the object.
- m_referenceCount = NULL;
- return;
- }
- }
-
- switch (m_type) {
- case NIL:
- // Nothing to do
- break;
-
- case NUMBER:
- delete (double*)m_value;
- break;
-
- case BOOLEAN:
- delete (bool*)m_value;
- break;
-
- case STRING:
- delete (std::string*)m_value;
- break;
-
- case RECT2D:
- delete (Rect2D*)m_value;
- break;
-
- case AABOX:
- delete (AABox*)m_value;
- break;
-
- case VECTOR2:
- delete (Vector2*)m_value;
- break;
-
- case VECTOR3:
- delete (Vector3*)m_value;
- break;
-
- case VECTOR4:
- delete (Vector4*)m_value;
- break;
-
- case MATRIX2:
- delete (Matrix2*)m_value;
- break;
-
- case MATRIX3:
- delete (Matrix3*)m_value;
- break;
-
- case MATRIX4:
- delete (Matrix4*)m_value;
- break;
-
- case QUAT:
- delete (Quat*)m_value;
- break;
-
- case COORDINATEFRAME:
- delete (CoordinateFrame*)m_value;
- break;
-
- case COLOR1:
- delete (Color1*)m_value;
- break;
-
- case COLOR3:
- delete (Color3*)m_value;
- break;
-
- case COLOR4:
- delete (Color4*)m_value;
- break;
-
- case ARRAY:
- delete (Array<AnyVal>*)m_value;
- break;
-
- case TABLE:
- delete (Table<std::string, AnyVal>*)m_value;
- break;
-
- default:
- debugAssertM(false, "Internal error: no destructor for this type.");
- }
-
- m_value = NULL;
-}
-
-
-AnyVal& AnyVal::operator=(const AnyVal& v) {
- deleteValue();
-
- m_type = v.m_type;
-
- m_referenceCount = v.m_referenceCount;
-
- if (isSharedType()) {
- ++(*m_referenceCount);
- m_value = v.m_value;
- } else {
- m_value = v.copyValue();
- }
-
- return *this;
-}
-
-
-void* AnyVal::copyValue() const {
- switch (m_type) {
- case NIL:
- return NULL;
-
- case NUMBER:
- return new double(*(double*)m_value);
-
- case BOOLEAN:
- return new bool(*(bool*)m_value);
-
- case STRING:
- return new std::string(*(std::string*)m_value);
-
- case RECT2D:
- return new Rect2D(*(Rect2D*)m_value);
-
- case AABOX:
- return new AABox(*(AABox*)m_value);
-
- case VECTOR2:
- return new Vector2(*(Vector2*)m_value);
-
- case VECTOR3:
- return new Vector3(*(Vector3*)m_value);
-
- case VECTOR4:
- return new Vector4(*(Vector4*)m_value);
-
- case MATRIX2:
- return new Matrix2(*(Matrix2*)m_value);
-
- case MATRIX3:
- return new Matrix3(*(Matrix3*)m_value);
-
- case MATRIX4:
- return new Matrix4(*(Matrix4*)m_value);
-
- case QUAT:
- return new Quat(*(Quat*)m_value);
-
- case COORDINATEFRAME:
- return new CoordinateFrame(*(CoordinateFrame*)m_value);
-
- case COLOR1:
- return new Color1(*(Color1*)m_value);
-
- case COLOR3:
- return new Color3(*(Color3*)m_value);
-
- case COLOR4:
- return new Color4(*(Color4*)m_value);
-
- case ARRAY:
- return new Array<AnyVal>(*(Array<AnyVal>*)m_value);
-
- case TABLE:
- return new Table<std::string, AnyVal>(*(Table<std::string, AnyVal>*)m_value);
-
- default:
- debugAssertM(false, "Internal error: no assignment operator for this type.");
- return NULL;
- }
-}
-
-AnyVal::Type AnyVal::type() const {
- return m_type;
-}
-
-
-static bool legalIdentifier(const std::string& s) {
- if (s.size() == 0) {
- return false;
- }
-
- if (! isLetter(s[0]) || (s[0] == '_')) {
- return false;
- }
-
- bool ok = true;
-
- for (unsigned int i = 1; i < s.size(); ++i) {
- ok &= isDigit(s[i]) || isLetter(s[i]) || (s[i] == '_');
- }
-
- return ok;
-}
-
-
-void AnyVal::serialize(G3D::TextOutput& t) const {
- switch (m_type) {
- case NIL:
- t.writeSymbol("Nil");
- break;
-
- case NUMBER:
- t.printf("%g", *(double*)m_value);
- break;
-
- case BOOLEAN:
- t.writeBoolean(*(bool*)m_value);
- break;
-
- case STRING:
- t.writeString(*(std::string*)m_value);
- break;
-
- case RECT2D:
- t.printf("R(%g, %g, %g, %g)", ((Rect2D*)m_value)->x0(), ((Rect2D*)m_value)->y0(),
- ((Rect2D*)m_value)->width(), ((Rect2D*)m_value)->height());
- break;
-
- case AABOX:
- t.printf("AAB(V3(%g, %g, %g), V3(%g, %g, %g))",
- aabox().low().x,
- aabox().low().y,
- aabox().low().z,
- aabox().high().x,
- aabox().high().y,
- aabox().high().z);
- break;
-
- case VECTOR2:
- t.printf("V2(%g, %g)", ((Vector2*)m_value)->x, ((Vector2*)m_value)->y);
- break;
-
- case VECTOR3:
- t.printf("V3(%g, %g, %g)", ((Vector3*)m_value)->x, ((Vector3*)m_value)->y, ((Vector3*)m_value)->z);
- break;
-
- case VECTOR4:
- t.printf("V4(%g, %g, %g, %g)", ((Vector4*)m_value)->x, ((Vector4*)m_value)->y, ((Vector4*)m_value)->z, ((Vector4*)m_value)->w);
- break;
-
- case MATRIX2:
- {
- const Matrix2& m = *(Matrix2*)m_value;
- t.printf("M2(\n");
- t.pushIndent();
- t.printf("%10.5f, %10.5f,\n%10.5f, %10.5f)",
- m[0][0], m[0][1],
- m[1][0], m[1][1]);
- t.popIndent();
- }
- break;
-
- case MATRIX3:
- {
- const Matrix3& m = *(Matrix3*)m_value;
- t.printf("M3(\n");
- t.pushIndent();
- t.printf("%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f,\n%10.5f, %10.5f, %10.5f)",
- m[0][0], m[0][1], m[0][2],
- m[1][0], m[1][1], m[1][2],
- m[2][0], m[2][1], m[2][2]);
- t.popIndent();
- }
- break;
-
- case MATRIX4:
- {
- const Matrix4& m = *(Matrix4*)m_value;
- t.printf("M4(\n");
- t.pushIndent();
- t.printf(
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f)",
- m[0][0], m[0][1], m[0][2], m[0][3],
- m[1][0], m[1][1], m[1][2], m[1][3],
- m[2][0], m[2][1], m[2][2], m[2][3],
- m[3][0], m[3][1], m[3][2], m[3][3]);
- t.popIndent();
- }
- break;
-
- case QUAT:
- t.printf("Q(%g, %g, %g, %g)", ((Quat*)m_value)->x, ((Quat*)m_value)->y, ((Quat*)m_value)->z, ((Quat*)m_value)->w);
- break;
-
- case COORDINATEFRAME:
- {
- const CoordinateFrame& c = *(CoordinateFrame*)m_value;
- float x,y,z,yaw,pitch,roll;
- c.getXYZYPRDegrees(x,y,z,yaw,pitch,roll);
- t.printf("CF(V3(%g,%g,%g), %g, %g, %g)", x, y, z, yaw, pitch, roll);
- /*
- t.pushIndent();
- t.printf(
- "CF(\n%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f,\n"
- "%10.5f, %10.5f, %10.5f, %10.5f)",
- c.rotation[0][0], c.rotation[0][1], c.rotation[0][2], c.translation.x,
- c.rotation[1][0], c.rotation[1][1], c.rotation[1][2], c.translation.y,
- c.rotation[2][0], c.rotation[2][1], c.rotation[2][2], c.translation.z);
- t.popIndent();
- */
- }
- break;
-
- case COLOR1:
- t.printf("C1(%g)", ((Color1*)m_value)->value);
- break;
-
- case COLOR3:
- t.printf("C3(%g, %g, %g)", ((Color3*)m_value)->r, ((Color3*)m_value)->g, ((Color3*)m_value)->b);
- break;
-
- case COLOR4:
- t.printf("C4(%g, %g, %g, %g)", ((Color4*)m_value)->r, ((Color4*)m_value)->g, ((Color4*)m_value)->b, ((Color4*)m_value)->a);
- break;
-
- case ARRAY:
- {
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- t.printf("[\n");
- t.pushIndent();
- for (int i = 0; i < a.size(); ++i) {
- a[i].serialize(t);
- if (i != a.size() - 1) {
- t.printf(", \n");
- }
- }
- t.printf("]");
- t.popIndent();
- }
- break;
-
- case TABLE:
- {
- const Table<std::string, AnyVal>& a = *(Table<std::string, AnyVal>*)m_value;
- t.printf("{\n");
- t.pushIndent();
- Table<std::string, AnyVal>::Iterator i = a.begin();
- const Table<std::string, AnyVal>::Iterator end = a.end();
- while (i != end) {
- // Quote names that are not legal C++ identifiers
- if (! legalIdentifier(i->key)) {
- t.printf("'%s' ", i->key.c_str());
- } else {
- t.writeSymbol(i->key);
- }
- t.printf("= ");
-
- i->value.serialize(t);
-
- if (i != end) {
- t.printf("\n");
- }
- ++i;
- }
- t.popIndent();
- t.printf("}");
- }
- break;
-
- default:
- debugAssertM(false, "Internal error: no serialize method for this type.");
- }
-}
-
-
-std::string AnyVal::toString() const {
- TextOutput t;
- serialize(t);
- std::string s;
- t.commitString(s);
- return s;
-}
-
-void AnyVal::deserialize(G3D::TextInput& t) {
- deleteValue();
- m_type = NIL;
- m_value = NULL;
-
- if (! t.hasMore()) {
- return;
- }
-
- switch (t.peek().type()) {
- case Token::END:
- // should never get here because of the hasMore check above
- return;
- break;
-
- case Token::NUMBER:
- m_type = NUMBER;
- m_value = new double(t.readNumber());
- break;
-
- case Token::STRING:
- m_type = STRING;
- m_value = new std::string(t.readString());
- break;
-
- case Token::NEWLINE:
- m_type = STRING;
- m_value = new std::string(t.readNewline());
- break;
-
- case Token::COMMENT:
- m_type = STRING;
- m_value = new std::string(t.readComment());
- break;
-
- case Token::BOOLEAN:
- m_type = BOOLEAN;
- m_value = new bool(t.readBoolean());
- break;
-
- case Token::SYMBOL:
- {
- std::string s = t.readSymbol();
- if (s == "NIL") {
- break;
-
- } else if (s == "true") {
-
- m_type = BOOLEAN;
- m_value = new bool(true);
-
- } else if (s == "false") {
-
- m_type = BOOLEAN;
- m_value = new bool(false);
-
- } else if (s == "R") {
-
- m_type = RECT2D;
- t.readSymbol("(");
- float x,y,w,h;
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(",");
- w = (float)t.readNumber();
- t.readSymbol(",");
- h = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Rect2D(Rect2D::xywh(x, y, w, h));
-
- } else if (s == "AAB") {
-
- m_type = AABOX;
- Vector3 v[2];
- t.readSymbol("(");
- for (int i = 0; i < 2; ++i) {
- t.readSymbols("V3", "(");
- v[i].x = (float)t.readNumber();
- t.readSymbol(",");
- v[i].y = (float)t.readNumber();
- t.readSymbol(",");
- v[i].z = (float)t.readNumber();
- t.readSymbol(",");
- if (i == 0) {
- t.readSymbol(",");
- }
- }
- t.readSymbol(")");
- m_value = new AABox(v[0], v[1]);
-
- } else if (s == "V2") {
-
- t.readSymbol("(");
- Vector2 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector2(v);
- m_type = VECTOR2;
-
- } else if (s == "V3") {
-
- t.readSymbol("(");
- Vector3 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(",");
- v.z = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector3(v);
- m_type = VECTOR3;
-
- } else if (s == "V4") {
-
- t.readSymbol("(");
- Vector4 v;
- v.x = (float)t.readNumber();
- t.readSymbol(",");
- v.y = (float)t.readNumber();
- t.readSymbol(",");
- v.z = (float)t.readNumber();
- t.readSymbol(",");
- v.w = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Vector4(v);
- m_type = VECTOR4;
-
- } else if (s == "M2") {
-
- t.readSymbol("(");
- Matrix2 m;
- for (int r = 0; r < 2; ++r) {
- for (int c = 0; c < 2; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 1) || (r != 1)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix2(m);
- m_type = MATRIX2;
-
- } else if (s == "M3") {
-
- t.readSymbol("(");
- Matrix3 m;
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 2) || (r != 2)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix3(m);
- m_type = MATRIX3;
-
- } else if (s == "M4") {
-
- t.readSymbol("(");
- Matrix4 m;
- for (int r = 0; r < 4; ++r) {
- for (int c = 0; c < 4; ++c) {
- m[r][c] = (float)t.readNumber();
- if ((c != 3) || (r != 3)) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new Matrix4(m);
- m_type = MATRIX4;
-
- } else if (s == "Q") {
-
- t.readSymbol("(");
- Quat q;
- q.x = (float)t.readNumber();
- t.readSymbol(",");
- q.y = (float)t.readNumber();
- t.readSymbol(",");
- q.z = (float)t.readNumber();
- t.readSymbol(",");
- q.w = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Quat(q);
- m_type = QUAT;
-
- } else if (s == "CF") {
-
- t.readSymbol("(");
- CoordinateFrame m;
- if (t.peek().type() == Token::SYMBOL) {
- // Angle format
- float x, y, z, yaw, roll, pitch;
- t.readSymbols("V3", "(");
- x = (float)t.readNumber();
- t.readSymbol(",");
- y = (float)t.readNumber();
- t.readSymbol(",");
- z = (float)t.readNumber();
- t.readSymbols(")", ",");
- yaw = (float)t.readNumber();
- t.readSymbol(",");
- pitch = (float)t.readNumber();
- roll = 0;
- if (t.peek().string() == ",") {
- t.readSymbol(",");
- roll = (float)t.readNumber();
- }
- m = CoordinateFrame::fromXYZYPRDegrees(x, y, z, yaw, pitch, roll);
- } else {
- // Matrix format
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- m.rotation[r][c] = (float)t.readNumber();
- }
- m.translation[r] = (float)t.readNumber();
- if (r != 2) {
- t.readSymbol(",");
- }
- }
- }
- t.readSymbol(")");
- m_value = new CoordinateFrame(m);
- m_type = COORDINATEFRAME;
-
- } else if (s == "C1") {
-
- t.readSymbol("(");
- float v = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color1(v);
- m_type = COLOR1;
-
- } else if (s == "C3") {
-
- t.readSymbol("(");
- Color3 c;
- c.r = (float)t.readNumber();
- t.readSymbol(",");
- c.g = (float)t.readNumber();
- t.readSymbol(",");
- c.b = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color3(c);
- m_type = COLOR3;
-
- } else if (s == "C4") {
-
- t.readSymbol("(");
- Color4 c;
- c.r = (float)t.readNumber();
- t.readSymbol(",");
- c.g = (float)t.readNumber();
- t.readSymbol(",");
- c.b = (float)t.readNumber();
- t.readSymbol(",");
- c.a = (float)t.readNumber();
- t.readSymbol(")");
- m_value = new Color4(c);
- m_type = COLOR4;
-
- } else if (s == "[") {
-
- // Array
- m_type = ARRAY;
- m_value = new Array<AnyVal>();
- m_referenceCount = new int(1);
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- Token peek = t.peek();
- while ((peek.type() != Token::SYMBOL) || (peek.string() != "]")) {
- // Avoid copying large objects
- a.next().deserialize(t);
-
- peek = t.peek();
- if (peek.type() != Token::SYMBOL) {
- throw CorruptText("Expected ',' or ']'", peek);
- } else if (peek.string() == ",") {
- t.readSymbol(",");
- } else if (peek.string() != "]") {
- throw CorruptText("Missing ']'", peek);
- }
- }
- t.readSymbol("]");
-
- } else if (s == "{") {
-
- // Table
- m_type = TABLE;
- m_value = new Table<std::string, AnyVal>();
- m_referenceCount = new int(1);
- Table<std::string, AnyVal>& a = *(Table<std::string, AnyVal>*)m_value;
-
- Token peek = t.peek();
- while ((peek.type() != Token::SYMBOL) || (peek.string() != "}")) {
-
- std::string key;
- // Get the name
- if (peek.type() == Token::SYMBOL) {
- key = t.readSymbol();
- } else if (peek.extendedType() == Token::SINGLE_QUOTED_TYPE) {
- key = t.readString();
- } else {
- throw CorruptText("Expected name inside table", peek);
- }
-
- t.readSymbol("=");
-
- // Avoid copying large values
- a.set(key, AnyVal());
- a[key].deserialize(t);
-
- peek = t.peek();
- if ((peek.type() != Token::SYMBOL) && (peek.extendedType() != Token::SINGLE_QUOTED_TYPE)) {
- throw CorruptText("Missing expected name or '}'", peek);
- }
- }
- t.readSymbol("}");
-
- } else {
- throw CorruptText("Invalid value type.", t.peek());
- } // dispatch on symbol type
- } // scope
- break;
- }
-}
-
-
-AnyVal& AnyVal::operator[](const char* key) {
- return this->operator[]((std::string)key);
-}
-
-
-const AnyVal& AnyVal::operator[](const char* key) const {
- return this->operator[]((std::string)key);
-}
-
-
-AnyVal& AnyVal::operator[](const std::string& key) {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- makeMutable();
-
- Table<std::string, AnyVal>& t = *(Table<std::string, AnyVal>*)m_value;
-
- if (! t.containsKey(key)) {
- t.set(key, AnyVal());
- }
-
- return t[key];
-}
-
-
-const AnyVal& AnyVal::operator[](const std::string& key) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (! t.containsKey(key)) {
- throw KeyNotFound(key);
- }
-
- return t[key];
-}
-
-
-void AnyVal::append(const AnyVal& v) {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
- makeMutable();
-
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- a.append(v);
-}
-
-
-void AnyVal::getKeys(Array<std::string>& keys) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
- t.getKeys(keys);
-}
-
-
-int AnyVal::size() const {
- switch (m_type) {
- case TABLE:
- {
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
- return t.size();
- }
-
- case ARRAY:
- {
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
- return a.size();
- }
-
- default:
- throw WrongType(ARRAY, m_type);
- }
-}
-
-
-AnyVal& AnyVal::operator[](int i) {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
- makeMutable();
-
- Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- if (i < 0) {
- throw IndexOutOfBounds(i, a.size());
- }
-
- if (a.size() <= i) {
- a.resize(i + 1);
- }
-
- return a[i];
-}
-
-
-const AnyVal& AnyVal::operator[](int i) const {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
-
- const Array<AnyVal>& a = *(Array<AnyVal>*)m_value;
-
- if (a.size() <= i || i < 0) {
- throw IndexOutOfBounds(i, a.size());
- }
-
- return a[i];
-}
-
-
-void AnyVal::makeMutable() {
- if (*m_referenceCount > 1) {
- // This is a shared instance
- --(*m_referenceCount);
- m_referenceCount = new int(1);
- m_value = copyValue();
- }
-}
-
-bool AnyVal::boolean() const {
- if (m_type != BOOLEAN) {
- throw WrongType(BOOLEAN, m_type);
- }
-
- return *(bool*)m_value;
-}
-
-
-bool AnyVal::boolean(bool defaultVal) const {
- if (m_type != BOOLEAN) {
- return defaultVal;
- }
-
- return *(bool*)m_value;
-}
-
-
-const std::string& AnyVal::string() const {
- if (m_type != STRING) {
- throw WrongType(STRING, m_type);
- }
-
- return *(std::string*)m_value;
-}
-
-
-const std::string& AnyVal::string(const std::string& defaultVal) const {
- if (m_type != STRING) {
- return defaultVal;
- } else {
- return *(std::string*)m_value;
- }
-}
-
-
-double AnyVal::number() const {
- if (m_type != NUMBER) {
- throw WrongType(NUMBER, m_type);
- }
-
- return *(double*)m_value;
-}
-
-
-double AnyVal::number(double defaultVal) const {
- if (m_type != NUMBER) {
- return defaultVal;
- } else {
- return *(double*)m_value;
- }
-}
-
-
-const Rect2D& AnyVal::rect2D() const {
- if (m_type != RECT2D) {
- throw WrongType(RECT2D, m_type);
- }
-
- return *(Rect2D*)m_value;
-}
-
-
-const Rect2D& AnyVal::rect2D(const Rect2D& defaultVal) const {
- if (m_type != RECT2D) {
- return defaultVal;
- } else {
- return *(Rect2D*)m_value;
- }
-}
-
-
-const AABox& AnyVal::aabox() const {
- if (m_type != AABOX) {
- throw WrongType(AABOX, m_type);
- }
-
- return *(AABox*)m_value;
-}
-
-
-const AABox& AnyVal::aabox(const AABox& defaultVal) const {
- if (m_type != AABOX) {
- return defaultVal;
- } else {
- return *(AABox*)m_value;
- }
-}
-
-
-const Color1& AnyVal::color1() const {
- if (m_type != COLOR1) {
- throw WrongType(COLOR1, m_type);
- }
-
- return *(Color1*)m_value;
-}
-
-
-const Color1& AnyVal::color1(const Color1& defaultVal) const {
- if (m_type != COLOR1) {
- return defaultVal;
- } else {
- return *(Color1*)m_value;
- }
-}
-
-
-const Color3& AnyVal::color3() const {
- if (m_type != COLOR3) {
- throw WrongType(COLOR3, m_type);
- }
-
- return *(Color3*)m_value;
-}
-
-
-const Color3& AnyVal::color3(const Color3& defaultVal) const {
- if (m_type != COLOR3) {
- return defaultVal;
- } else {
- return *(Color3*)m_value;
- }
-}
-
-
-const Color4& AnyVal::color4() const {
- if (m_type != COLOR4) {
- throw WrongType(COLOR4, m_type);
- }
-
- return *(Color4*)m_value;
-}
-
-
-const Color4& AnyVal::color4(const Color4& defaultVal) const {
- if (m_type != COLOR4) {
- return defaultVal;
- } else {
- return *(Color4*)m_value;
- }
-}
-
-
-const Vector2& AnyVal::vector2() const {
- if (m_type != VECTOR2) {
- throw WrongType(VECTOR2, m_type);
- }
-
- return *(Vector2*)m_value;
-}
-
-
-const Vector2& AnyVal::vector2(const Vector2& defaultVal) const {
- if (m_type != VECTOR2) {
- return defaultVal;
- } else {
- return *(Vector2*)m_value;
- }
-}
-
-
-const Vector3& AnyVal::vector3() const {
- if (m_type != VECTOR3) {
- throw WrongType(VECTOR3, m_type);
- }
-
- return *(Vector3*)m_value;
-}
-
-
-const Vector3& AnyVal::vector3(const Vector3& defaultVal) const {
- if (m_type != VECTOR3) {
- return defaultVal;
- } else {
- return *(Vector3*)m_value;
- }
-}
-
-
-const Vector4& AnyVal::vector4() const {
- if (m_type != VECTOR4) {
- throw WrongType(VECTOR4, m_type);
- }
-
- return *(Vector4*)m_value;
-}
-
-
-const Vector4& AnyVal::vector4(const Vector4& defaultVal) const {
- if (m_type != VECTOR4) {
- return defaultVal;
- } else {
- return *(Vector4*)m_value;
- }
-}
-
-
-const CoordinateFrame& AnyVal::coordinateFrame() const {
- if (m_type != COORDINATEFRAME) {
- throw WrongType(COORDINATEFRAME, m_type);
- }
-
- return *(CoordinateFrame*)m_value;
-}
-
-
-const CoordinateFrame& AnyVal::coordinateFrame(const CoordinateFrame& defaultVal) const {
- if (m_type != COORDINATEFRAME) {
- return defaultVal;
- } else {
- return *(CoordinateFrame*)m_value;
- }
-}
-
-const Matrix2& AnyVal::matrix2(const Matrix2& defaultVal) const {
- if (m_type != MATRIX2) {
- return defaultVal;
- } else {
- return *(Matrix2*)m_value;
- }
-}
-
-
-const Matrix2& AnyVal::matrix2() const {
- if (m_type != MATRIX2) {
- throw WrongType(MATRIX2, m_type);
- }
-
- return *(Matrix2*)m_value;
-}
-
-
-const Matrix3& AnyVal::matrix3(const Matrix3& defaultVal) const {
- if (m_type != MATRIX3) {
- return defaultVal;
- } else {
- return *(Matrix3*)m_value;
- }
-}
-
-
-const Matrix3& AnyVal::matrix3() const {
- if (m_type != MATRIX3) {
- throw WrongType(MATRIX3, m_type);
- }
-
- return *(Matrix3*)m_value;
-}
-
-
-const Matrix4& AnyVal::matrix4(const Matrix4& defaultVal) const {
- if (m_type != MATRIX4) {
- return defaultVal;
- } else {
- return *(Matrix4*)m_value;
- }
-}
-
-
-const Matrix4& AnyVal::matrix4() const {
- if (m_type != MATRIX4) {
- throw WrongType(MATRIX4, m_type);
- }
-
- return *(Matrix4*)m_value;
-}
-
-
-const Quat& AnyVal::quat(const Quat& defaultVal) const {
- if (m_type != QUAT) {
- return defaultVal;
- } else {
- return *(Quat*)m_value;
- }
-}
-
-
-const Quat& AnyVal::quat() const {
- if (m_type != QUAT) {
- throw WrongType(QUAT, m_type);
- }
-
- return *(Quat*)m_value;
-}
-
-
-const AnyVal& AnyVal::get(const std::string& key, const AnyVal& defaultVal) const {
- if (m_type != TABLE) {
- return defaultVal;
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (t.containsKey(key)) {
- return t[key];
- } else {
- return defaultVal;
- }
-}
-
-
-const AnyVal& AnyVal::get(const std::string& key) const {
- if (m_type != TABLE) {
- throw WrongType(TABLE, m_type);
- }
-
- const Table<std::string, AnyVal>& t = *(const Table<std::string, AnyVal>*)m_value;
-
- if (t.containsKey(key)) {
- return t[key];
- } else {
- throw KeyNotFound(key);
- }
-}
-
-
-const AnyVal& AnyVal::get(int i, const AnyVal& defaultVal) const {
- if (m_type != ARRAY) {
- return defaultVal;
- }
-
- const Array<AnyVal>& a = *(const Array<AnyVal>*)m_value;
-
- if ((i >= 0) && (i < a.size())) {
- return a[i];
- } else {
- return defaultVal;
- }
-}
-
-
-const AnyVal& AnyVal::get(int i) const {
- if (m_type != ARRAY) {
- throw WrongType(ARRAY, m_type);
- }
-
- const Array<AnyVal>& a = *(const Array<AnyVal>*)m_value;
-
- if ((i >= 0) && (i < a.size())) {
- return a[i];
- } else {
- throw IndexOutOfBounds(i, a.size());
- }
-}
-
-}
diff --git a/dep/g3dlite/source/AreaMemoryManager.cpp b/dep/g3dlite/source/AreaMemoryManager.cpp
index 00cb33dc91f..33e5099c380 100644
--- a/dep/g3dlite/source/AreaMemoryManager.cpp
+++ b/dep/g3dlite/source/AreaMemoryManager.cpp
@@ -43,7 +43,7 @@ bool AreaMemoryManager::isThreadsafe() const {
AreaMemoryManager::Ref AreaMemoryManager::create(size_t sizeHint) {
- return new AreaMemoryManager(sizeHint);
+ return shared_ptr<AreaMemoryManager>(new AreaMemoryManager(sizeHint));
}
@@ -80,7 +80,7 @@ void AreaMemoryManager::free(void* x) {
void AreaMemoryManager::deallocateAll() {
- m_bufferArray.deleteAll();
+ m_bufferArray.invokeDeleteOnAllElements();
m_bufferArray.clear();
}
diff --git a/dep/g3dlite/source/BinaryInput.cpp b/dep/g3dlite/source/BinaryInput.cpp
index 19ab2722c5c..c6eafa5ce09 100644
--- a/dep/g3dlite/source/BinaryInput.cpp
+++ b/dep/g3dlite/source/BinaryInput.cpp
@@ -1,11 +1,11 @@
/**
- @file BinaryInput.cpp
+ \file BinaryInput.cpp
- @author Morgan McGuire, graphics3d.com
- Copyright 2001-2007, Morgan McGuire. All rights reserved.
+ \author Morgan McGuire, graphics3d.com
+ Copyright 2001-2013, Morgan McGuire. All rights reserved.
- @created 2001-08-09
- @edited 2010-03-05
+ \created 2001-08-09
+ \edited 2013-01-03
<PRE>
@@ -40,154 +40,17 @@
#include "G3D/FileSystem.h"
#include <zlib.h>
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- #include "zip.h"
+#include "../../zip.lib/include/zip.h"
#endif
#include <cstring>
namespace G3D {
-void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
- out.resize((int)n);
- // std::vector optimizes bool in a way that prevents fast reading
- for (int64 i = 0; i < n ; ++i) {
- out[i] = readBool8();
- }
-}
-
-
-void BinaryInput::readBool8(Array<bool>& out, int64 n) {
- out.resize(n);
- readBool8(out.begin(), n);
-}
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(&out[0], n);\
-}\
-\
-\
-void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
- out.resize(n);\
- read##ucase(out.begin(), n);\
-}
-
-
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-// Data structures that are one byte per element can be
-// directly copied, regardles of endian-ness.
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (sizeof(lcase) == 1) {\
- readBytes(out, n);\
- } else {\
- for (int64 i = 0; i < n ; ++i) {\
- out[i] = read##ucase();\
- }\
- }\
-}
-
-IMPLEMENT_READER(Bool8, bool)
-IMPLEMENT_READER(UInt8, uint8)
-IMPLEMENT_READER(Int8, int8)
-
-#undef IMPLEMENT_READER
-
-
-#define IMPLEMENT_READER(ucase, lcase)\
-void BinaryInput::read##ucase(lcase* out, int64 n) {\
- if (m_swapBytes) {\
- for (int64 i = 0; i < n; ++i) {\
- out[i] = read##ucase();\
- }\
- } else {\
- readBytes(out, sizeof(lcase) * n);\
- }\
-}
-
-
-IMPLEMENT_READER(UInt16, uint16)
-IMPLEMENT_READER(Int16, int16)
-IMPLEMENT_READER(UInt32, uint32)
-IMPLEMENT_READER(Int32, int32)
-IMPLEMENT_READER(UInt64, uint64)
-IMPLEMENT_READER(Int64, int64)
-IMPLEMENT_READER(Float32, float32)
-IMPLEMENT_READER(Float64, float64)
-
-#undef IMPLEMENT_READER
-
-void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
- // Load the next section of the file
- debugAssertM(m_filename != "<memory>", "Read past end of file.");
-
- int64 absPos = m_alreadyRead + m_pos;
-
- if (m_bufferLength < minLength) {
- // The current buffer isn't big enough to hold the chunk we want to read.
- // This happens if there was little memory available during the initial constructor
- // read but more memory has since been freed.
- m_bufferLength = minLength;
- debugAssert(m_freeBuffer);
- m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
- if (m_buffer == NULL) {
- throw "Tried to read a larger memory chunk than could fit in memory. (2)";
- }
- }
-
- m_alreadyRead = startPosition;
-
-# ifdef G3D_WIN32
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert(ret == toRead);
- fclose(file);
- file = NULL;
-
-# else
- FILE* file = fopen(m_filename.c_str(), "rb");
- debugAssert(file);
- int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
- debugAssert(ret == 0);
- size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
- ret = fread(m_buffer, 1, toRead, file);
- debugAssert((size_t)ret == (size_t)toRead);
- fclose(file);
- file = NULL;
-# endif
-
- m_pos = absPos - m_alreadyRead;
- debugAssert(m_pos >= 0);
-}
-
-
-
const bool BinaryInput::NO_COPY = false;
-
-static bool needSwapBytes(G3DEndian fileEndian) {
- return (fileEndian != System::machineEndian());
-}
/** Helper used by the constructors for decompression */
-static uint32 readUInt32(const uint8* data, bool swapBytes) {
+static uint32 readUInt32FromBuffer(const uint8* data, bool swapBytes) {
if (swapBytes) {
uint8 out[4];
out[0] = data[3];
@@ -201,12 +64,6 @@ static uint32 readUInt32(const uint8* data, bool swapBytes) {
}
-void BinaryInput::setEndian(G3DEndian e) {
- m_fileEndian = e;
- m_swapBytes = needSwapBytes(m_fileEndian);
-}
-
-
BinaryInput::BinaryInput(
const uint8* data,
int64 dataLen,
@@ -227,26 +84,26 @@ BinaryInput::BinaryInput(
if (compressed) {
// Read the decompressed size from the first 4 bytes
- m_length = G3D::readUInt32(data, m_swapBytes);
+ m_length = readUInt32FromBuffer(data, m_swapBytes);
debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
- unsigned long L = m_length;
+ unsigned long L = (unsigned long)m_length;
// Decompress with zlib
- int64 result = uncompress(m_buffer, (unsigned long*)&L, data + 4, dataLen - 4);
+ int64 result = uncompress(m_buffer, &L, data + 4, (uLong)dataLen - 4);
m_length = L;
m_bufferLength = L;
debugAssert(result == Z_OK); (void)result;
} else {
- m_length = dataLen;
+ m_length = dataLen;
m_bufferLength = m_length;
if (! copyMemory) {
- debugAssert(!m_freeBuffer);
+ debugAssert(!m_freeBuffer);
m_buffer = const_cast<uint8*>(data);
} else {
- debugAssert(m_freeBuffer);
+ debugAssert(m_freeBuffer);
m_buffer = (uint8*)System::alignedMalloc(m_length, 16);
System::memcpy(m_buffer, data, dataLen);
}
@@ -254,10 +111,10 @@ BinaryInput::BinaryInput(
}
-BinaryInput::BinaryInput(
- const std::string& filename,
- G3DEndian fileEndian,
- bool compressed) :
+BinaryInput::BinaryInput
+(const std::string& filename,
+ G3DEndian fileEndian,
+ bool compressed) :
m_filename(filename),
m_bitPos(0),
m_bitString(0),
@@ -270,18 +127,16 @@ BinaryInput::BinaryInput(
m_freeBuffer(true) {
setEndian(fileEndian);
-
- // Update global file tracker
- _internal::currentFilesUsed.insert(m_filename);
-
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
std::string zipfile;
if (FileSystem::inZipfile(m_filename, zipfile)) {
// Load from zipfile
-// zipRead(filename, v, s);
+ FileSystem::markFileUsed(m_filename);
+ FileSystem::markFileUsed(zipfile);
- std::string internalFile = m_filename.substr(zipfile.length() + 1);
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(m_filename.substr(zipfile.length() + 1));
struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
@@ -291,29 +146,31 @@ BinaryInput::BinaryInput(
// sets machines up to use MMX, if they want
m_buffer = reinterpret_cast<uint8*>(System::alignedMalloc(m_length, 16));
struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
- {
- int64 test = zip_fread( zf, m_buffer, m_length );
- debugAssertM(test == m_length,
+ if (zf == NULL) {
+ throw std::string("\"") + internalFile + "\" inside \"" + zipfile + "\" could not be opened.";
+ } else {
+ const int64 bytesRead = zip_fread( zf, m_buffer, m_length );
+ debugAssertM(bytesRead == m_length,
internalFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
+ (void)bytesRead;
+ zip_fclose( zf );
}
- zip_fclose( zf );
}
zip_close( z );
if (compressed) {
decompress();
}
+
m_freeBuffer = true;
return;
}
#endif
-
// Figure out how big the file is and verify that it exists.
m_length = FileSystem::size(m_filename);
// Read the file into memory
- FILE* file = fopen(m_filename.c_str(), "rb");
+ FILE* file = FileSystem::fopen(m_filename.c_str(), "rb");
if (! file || (m_length == -1)) {
throw format("File not found: \"%s\"", m_filename.c_str());
@@ -346,8 +203,8 @@ BinaryInput::BinaryInput(
}
debugAssert(m_buffer);
- fread(m_buffer, m_bufferLength, sizeof(int8), file);
- fclose(file);
+ (void)fread(m_buffer, m_bufferLength, sizeof(int8), file);
+ FileSystem::fclose(file);
file = NULL;
if (compressed) {
@@ -359,13 +216,36 @@ BinaryInput::BinaryInput(
}
}
+BinaryInput::~BinaryInput() {
+
+ if (m_freeBuffer) {
+ System::alignedFree(m_buffer);
+ }
+ m_buffer = NULL;
+}
+
+
+std::string BinaryInput::readFixedLengthString(int numBytes) {
+ Array<char> str;
+ str.resize(numBytes + 1);
+
+ // Ensure NULL termination
+ str.last() = '\0';
+
+ readBytes(str.getCArray(), numBytes);
+
+ // Copy up to the first NULL
+ return std::string(str.getCArray());
+}
+
+
void BinaryInput::decompress() {
// Decompress
// Use the existing buffer as the source, allocate
// a new buffer to use as the destination.
int64 tempLength = m_length;
- m_length = G3D::readUInt32(m_buffer, m_swapBytes);
+ m_length = readUInt32FromBuffer(m_buffer, m_swapBytes);
// The file couldn't have better than 500:1 compression
alwaysAssertM(m_length < m_bufferLength * 500, "Compressed file header is corrupted");
@@ -377,8 +257,8 @@ void BinaryInput::decompress() {
debugAssert(isValidHeapPointer(tempBuffer));
debugAssert(isValidHeapPointer(m_buffer));
- unsigned long L = m_length;
- int64 result = uncompress(m_buffer, &L, tempBuffer + 4, tempLength - 4);
+ unsigned long L = (unsigned long)m_length;
+ int64 result = (int64)uncompress(m_buffer, &L, tempBuffer + 4, (uLong)tempLength - 4);
m_length = L;
m_bufferLength = m_length;
@@ -389,6 +269,70 @@ void BinaryInput::decompress() {
}
+void BinaryInput::setEndian(G3DEndian e) {
+ m_fileEndian = e;
+ m_swapBytes = (m_fileEndian != System::machineEndian());
+}
+
+
+void BinaryInput::loadIntoMemory(int64 startPosition, int64 minLength) {
+ // Load the next section of the file
+ debugAssertM(m_filename != "<memory>", "Read past end of file.");
+
+ int64 absPos = m_alreadyRead + m_pos;
+
+ if (m_bufferLength < minLength) {
+ // The current buffer isn't big enough to hold the chunk we want to read.
+ // This happens if there was little memory available during the initial constructor
+ // read but more memory has since been freed.
+ m_bufferLength = minLength;
+ debugAssert(m_freeBuffer);
+ m_buffer = (uint8*)System::realloc(m_buffer, m_bufferLength);
+ if (m_buffer == NULL) {
+ throw "Tried to read a larger memory chunk than could fit in memory. (2)";
+ }
+ }
+
+ m_alreadyRead = startPosition;
+
+# ifdef G3D_WINDOWS
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ size_t ret = fseek(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert(ret == toRead);
+ fclose(file);
+ file = NULL;
+
+# else
+ FILE* file = fopen(m_filename.c_str(), "rb");
+ debugAssert(file);
+ int ret = fseeko(file, (off_t)m_alreadyRead, SEEK_SET);
+ debugAssert(ret == 0);
+ size_t toRead = (size_t)G3D::min<int64>(m_bufferLength, m_length - m_alreadyRead);
+ ret = fread(m_buffer, 1, toRead, file);
+ debugAssert((size_t)ret == (size_t)toRead);
+ fclose(file);
+ file = NULL;
+# endif
+
+ m_pos = absPos - m_alreadyRead;
+ debugAssert(m_pos >= 0);
+}
+
+
+void BinaryInput::prepareToRead(int64 nbytes) {
+ debugAssertM(m_length > 0, m_filename + " not found or corrupt.");
+ debugAssertM(m_pos + nbytes + m_alreadyRead <= m_length, "Read past end of file.");
+
+ if (m_pos + nbytes > m_bufferLength) {
+ loadIntoMemory(m_pos + m_alreadyRead, nbytes);
+ }
+}
+
+
void BinaryInput::readBytes(void* bytes, int64 n) {
prepareToRead(n);
debugAssert(isValidPointer(bytes));
@@ -398,14 +342,6 @@ void BinaryInput::readBytes(void* bytes, int64 n) {
}
-BinaryInput::~BinaryInput() {
-
- if (m_freeBuffer) {
- System::alignedFree(m_buffer);
- }
- m_buffer = NULL;
-}
-
uint64 BinaryInput::readUInt64() {
prepareToRead(8);
@@ -429,52 +365,47 @@ uint64 BinaryInput::readUInt64() {
}
-std::string BinaryInput::readString(int64 n) {
- prepareToRead(n);
- debugAssertM((m_pos + n) <= m_length, "Read past end of file");
-
- char *s = (char*)System::alignedMalloc(n + 1, 16);
- assert(s != NULL);
+std::string BinaryInput::readString(int64 maxLength) {
+ prepareToRead(maxLength);
- memcpy(s, m_buffer + m_pos, n);
- // There may not be a null, so make sure
- // we add one.
- s[n] = '\0';
-
- std::string out = s;
- System::alignedFree(s);
- s = NULL;
+ int64 n = 0;
+ while ((m_buffer[m_pos + n] != '\0') && (n != maxLength)) {
+ ++n;
+ }
- m_pos += n;
+ std::string s((char*)(m_buffer + m_pos), n);
- return out;
+ m_pos += maxLength;
+ return s;
}
std::string BinaryInput::readString() {
- int64 n = 0;
-
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ prepareToRead(1);
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
+ int64 n = 0;
+ bool hasNull = true;
+ while(m_buffer[m_pos + n] != '\0') {
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- (m_buffer[m_pos + n] != '\0')) {
- prepareToRead(1);
- ++n;
+ if ((m_pos + m_alreadyRead + n) == m_length) {
+ hasNull = false;
+ break;
}
+
+ prepareToRead(n + 1);
}
- // Consume NULL
- ++n;
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- return readString(n);
+ if (hasNull) {
+ skip(1);
+ }
+
+ return s;
}
static bool isNewline(char c) {
@@ -482,32 +413,48 @@ static bool isNewline(char c) {
}
std::string BinaryInput::readStringNewline() {
+ prepareToRead(1);
+
int64 n = 0;
+ bool hasNull = true;
+ bool hasNewline = false;
- if ((m_pos + m_alreadyRead + n) < (m_length - 1)) {
- prepareToRead(1);
- }
+ while(m_buffer[m_pos + n] != '\0') {
+ if ((m_pos + m_alreadyRead + n + 1) == m_length) {
+ hasNull = false;
+ break;
+ }
- if ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
+ if (isNewline(m_buffer[m_pos + n])) {
+ hasNull = false;
+ hasNewline = true;
+ break;
+ }
++n;
- while ( ((m_pos + m_alreadyRead + n) < (m_length - 1)) &&
- ! isNewline(m_buffer[m_pos + n])) {
-
- prepareToRead(1);
- ++n;
- }
+ prepareToRead(n + 1);
}
- const std::string s = readString(n);
-
- // Consume the newline
- char firstNLChar = readUInt8();
+ std::string s((char*)(m_buffer + m_pos), n);
+ m_pos += n;
- // Consume the 2nd newline
- if (isNewline(m_buffer[m_pos + 1]) && (m_buffer[m_pos + 1] != firstNLChar)) {
- readUInt8();
+ if (hasNull) {
+ skip(1);
+ }
+
+ if (hasNewline) {
+ if ((m_pos + m_alreadyRead + 2) != m_length) {
+ prepareToRead(2);
+ if (m_buffer[m_pos] == '\r' && m_buffer[m_pos + 1] == '\n') {
+ skip(2);
+ } else if (m_buffer[m_pos] == '\n' && m_buffer[m_pos + 1] == '\r') {
+ skip(2);
+ } else {
+ skip(1);
+ }
+ } else {
+ skip(1);
+ }
}
return s;
@@ -516,7 +463,7 @@ std::string BinaryInput::readStringNewline() {
std::string BinaryInput::readStringEven() {
std::string x = readString();
- if (hasMore() && (G3D::isOdd(x.length() + 1))) {
+ if (hasMore() && (G3D::isOdd((int)x.length() + 1))) {
skip(1);
}
return x;
@@ -618,4 +565,90 @@ void BinaryInput::endBits() {
m_bitPos = 0;
}
+
+void BinaryInput::readBool8(std::vector<bool>& out, int64 n) {
+ out.resize((int)n);
+ // std::vector optimizes bool in a way that prevents fast reading
+ for (int64 i = 0; i < n ; ++i) {
+ out[i] = readBool8();
+ }
+}
+
+
+void BinaryInput::readBool8(Array<bool>& out, int64 n) {
+ out.resize(n);
+ readBool8(out.begin(), n);
}
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(std::vector<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(&out[0], n);\
+}\
+\
+\
+void BinaryInput::read##ucase(Array<lcase>& out, int64 n) {\
+ out.resize(n);\
+ read##ucase(out.begin(), n);\
+}
+
+
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+// Data structures that are one byte per element can be
+// directly copied, regardles of endian-ness.
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (sizeof(lcase) == 1) {\
+ readBytes(out, n);\
+ } else {\
+ for (int64 i = 0; i < n ; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ }\
+}
+
+IMPLEMENT_READER(Bool8, bool)
+IMPLEMENT_READER(UInt8, uint8)
+IMPLEMENT_READER(Int8, int8)
+
+#undef IMPLEMENT_READER
+
+
+#define IMPLEMENT_READER(ucase, lcase)\
+void BinaryInput::read##ucase(lcase* out, int64 n) {\
+ if (m_swapBytes) {\
+ for (int64 i = 0; i < n; ++i) {\
+ out[i] = read##ucase();\
+ }\
+ } else {\
+ readBytes(out, sizeof(lcase) * n);\
+ }\
+}
+
+
+IMPLEMENT_READER(UInt16, uint16)
+IMPLEMENT_READER(Int16, int16)
+IMPLEMENT_READER(UInt32, uint32)
+IMPLEMENT_READER(Int32, int32)
+IMPLEMENT_READER(UInt64, uint64)
+IMPLEMENT_READER(Int64, int64)
+IMPLEMENT_READER(Float32, float32)
+IMPLEMENT_READER(Float64, float64)
+
+#undef IMPLEMENT_READER
+
+} // namespace G3D
+
diff --git a/dep/g3dlite/source/BinaryOutput.cpp b/dep/g3dlite/source/BinaryOutput.cpp
index 81fa9822206..b174751c8c3 100644
--- a/dep/g3dlite/source/BinaryOutput.cpp
+++ b/dep/g3dlite/source/BinaryOutput.cpp
@@ -2,7 +2,7 @@
@file BinaryOutput.cpp
@author Morgan McGuire, http://graphics.cs.williams.edu
- Copyright 2002-2010, Morgan McGuire, All rights reserved.
+ Copyright 2002-2011, Morgan McGuire, All rights reserved.
@created 2002-02-20
@edited 2010-03-17
@@ -22,10 +22,6 @@
# include <errno.h>
#endif
-#ifdef __CYGWIN__
-# include <errno.h>
-#endif
-
// Largest memory buffer that the system will use for writing to
// disk. After this (or if the system runs out of memory)
// chunks of the file will be dumped to disk.
@@ -121,10 +117,11 @@ void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
uint8* newBuffer = NULL;
if ((m_filename == "<memory>") || (newBufferLen < MAX_BINARYOUTPUT_BUFFER_SIZE)) {
- // We're either writing to memory (in which case we *have* to try and allocate)
- // or we've been asked to allocate a reasonable size buffer.
+ // We're either writing to memory (in which case we *have* to
+ // try and allocate) or we've been asked to allocate a
+ // reasonable size buffer.
- //debugPrintf(" realloc(%d)\n", newBufferLen);
+ // debugPrintf(" realloc(%d)\n", newBufferLen);
newBuffer = (uint8*)System::realloc(m_buffer, newBufferLen);
if (newBuffer != NULL) {
m_maxBufferLen = newBufferLen;
@@ -134,9 +131,11 @@ void BinaryOutput::reallocBuffer(size_t bytes, size_t oldBufferLen) {
if ((newBuffer == NULL) && (bytes > 0)) {
// Realloc failed; we're probably out of memory. Back out
// the entire call and try to dump some data to disk.
+ alwaysAssertM(m_filename != "<memory>", "Realloc failed while writing to memory.");
m_bufferLen = oldBufferLen;
reserveBytesWhenOutOfMemory(bytes);
} else {
+ // Realloc succeeded
m_buffer = newBuffer;
debugAssert(isValidHeapPointer(m_buffer));
}
@@ -152,7 +151,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
// Dump the contents to disk. In order to enable seeking backwards,
// we keep the last 10 MB in memory.
- int writeBytes = m_bufferLen - 10 * 1024 * 1024;
+ size_t writeBytes = m_bufferLen - 10 * 1024 * 1024;
if (writeBytes < m_bufferLen / 3) {
// We're going to write less than 1/3 of the file;
@@ -164,11 +163,12 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
//debugPrintf("Writing %d bytes to disk\n", writeBytes);
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
+ alwaysAssertM(m_filename != "<memory>", "Writing memory file");
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
debugAssert(file);
size_t count = fwrite(m_buffer, 1, writeBytes, file);
- debugAssert((int)count == writeBytes); (void)count;
+ debugAssert(count == writeBytes); (void)count;
fclose(file);
file = NULL;
@@ -181,7 +181,7 @@ void BinaryOutput::reserveBytesWhenOutOfMemory(size_t bytes) {
debugAssert(m_bufferLen < m_maxBufferLen);
debugAssert(m_bufferLen >= 0);
debugAssert(m_pos >= 0);
- debugAssert(m_pos <= m_bufferLen);
+ debugAssert(m_pos <= (int64)m_bufferLen);
// Shift the unwritten data back appropriately in the buffer.
debugAssert(isValidHeapPointer(m_buffer));
@@ -273,45 +273,49 @@ bool BinaryOutput::ok() const {
}
-void BinaryOutput::compress() {
+void BinaryOutput::compress(int level) {
if (m_alreadyWritten > 0) {
throw "Cannot compress huge files (part of this file has already been written to disk).";
}
+ debugAssertM(! m_committed, "Cannot compress after committing.");
+ alwaysAssertM(m_bufferLen < 0xFFFFFFFF, "Compress only works for 32-bit files.");
+
+ // This is the worst-case size, as mandated by zlib
+ unsigned long compressedSize = iCeil(m_bufferLen * 1.001) + 12;
+
+ // Save the old buffer and reallocate to the worst-case size
+ const uint8* src = m_buffer;
+ const uint32 srcSize = (uint32)m_bufferLen;
+
+ // add space for the 4-byte header
+ m_maxBufferLen = compressedSize + 4;
+ m_buffer = (uint8*)System::malloc(m_maxBufferLen);
+
+ // Write the header containing the old buffer size, which is needed for decompression
+ {
+ const uint8* convert = (const uint8*)&srcSize;
+ if (m_swapBytes) {
+ m_buffer[0] = convert[3];
+ m_buffer[1] = convert[2];
+ m_buffer[2] = convert[1];
+ m_buffer[3] = convert[0];
+ } else {
+ m_buffer[0] = convert[0];
+ m_buffer[1] = convert[1];
+ m_buffer[2] = convert[2];
+ m_buffer[3] = convert[3];
+ }
+ }
- // Old buffer size
- int L = m_bufferLen;
- uint8* convert = (uint8*)&L;
-
- // Zlib requires the output buffer to be this big
- unsigned long newSize = iCeil(m_bufferLen * 1.01) + 12;
- uint8* temp = (uint8*)System::malloc(newSize);
- int result = compress2(temp, &newSize, m_buffer, m_bufferLen, 9);
+ // Compress and write after the header
+ int result = compress2(m_buffer + 4, &compressedSize, src, srcSize, iClamp(level, 0, 9));
debugAssert(result == Z_OK); (void)result;
-
- // Write the header
- if (m_swapBytes) {
- m_buffer[0] = convert[3];
- m_buffer[1] = convert[2];
- m_buffer[2] = convert[1];
- m_buffer[3] = convert[0];
- } else {
- m_buffer[0] = convert[0];
- m_buffer[1] = convert[1];
- m_buffer[2] = convert[2];
- m_buffer[3] = convert[3];
- }
-
- // Write the data
- if ((int64)newSize + 4 > (int64)m_maxBufferLen) {
- m_maxBufferLen = newSize + 4;
- m_buffer = (uint8*)System::realloc(m_buffer, m_maxBufferLen);
- }
- m_bufferLen = newSize + 4;
- System::memcpy(m_buffer + 4, temp, newSize);
+ m_bufferLen = compressedSize + 4;
m_pos = m_bufferLen;
- System::free(temp);
+ // Free the old data
+ System::free((void*)src);
}
@@ -320,6 +324,10 @@ void BinaryOutput::commit(bool flush) {
m_committed = true;
debugAssertM(m_beginEndBits == 0, "Missing endBits before commit");
+ if (m_filename == "<memory>") {
+ return;
+ }
+
// Make sure the directory exists.
std::string root, base, ext, path;
Array<std::string> pathArray;
@@ -332,6 +340,7 @@ void BinaryOutput::commit(bool flush) {
const char* mode = (m_alreadyWritten > 0) ? "ab" : "wb";
+ alwaysAssertM(m_filename != "<memory>", "Writing to memory file");
FILE* file = FileSystem::fopen(m_filename.c_str(), mode);
if (! file) {
@@ -345,7 +354,7 @@ void BinaryOutput::commit(bool flush) {
if (m_buffer != NULL) {
m_alreadyWritten += m_bufferLen;
- int success = fwrite(m_buffer, m_bufferLen, 1, file);
+ size_t success = fwrite(m_buffer, m_bufferLen, 1, file);
(void)success;
debugAssertM(success == 1, std::string("Could not write to '") + m_filename + "'");
}
@@ -427,7 +436,7 @@ void BinaryOutput::writeUInt64(uint64 u) {
void BinaryOutput::writeString(const char* s) {
// +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
+ size_t len = strlen(s) + 1;
debugAssert(m_beginEndBits == 0);
reserveBytes(len);
@@ -438,7 +447,7 @@ void BinaryOutput::writeString(const char* s) {
void BinaryOutput::writeStringEven(const char* s) {
// +1 is because strlen doesn't count the null
- int len = strlen(s) + 1;
+ size_t len = strlen(s) + 1;
reserveBytes(len);
System::memcpy(m_buffer + m_pos, s, len);
@@ -452,8 +461,14 @@ void BinaryOutput::writeStringEven(const char* s) {
void BinaryOutput::writeString32(const char* s) {
- writeUInt32(strlen(s) + 1);
- writeString(s);
+ // Write the NULL and count it
+ size_t len = strlen(s) + 1;
+ writeUInt32((uint32)len);
+
+ debugAssert(m_beginEndBits == 0);
+ reserveBytes(len);
+ System::memcpy(m_buffer + m_pos, s, len);
+ m_pos += len;
}
diff --git a/dep/g3dlite/source/Box.cpp b/dep/g3dlite/source/Box.cpp
index f7c112ae3a5..3ee3dc04013 100644
--- a/dep/g3dlite/source/Box.cpp
+++ b/dep/g3dlite/source/Box.cpp
@@ -1,11 +1,11 @@
/**
- @file Box.cpp
+ \file G3D.lib/source/Box.cpp
Box class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu, Michael Mara
- @created 2001-06-02
- @edited 2006-02-05
+ \created 2001-06-02
+ \edited 2013-04-13
*/
#include "G3D/Box.h"
@@ -13,126 +13,207 @@
#include "G3D/Plane.h"
#include "G3D/AABox.h"
#include "G3D/CoordinateFrame.h"
+#include "G3D/vectorMath.h"
+#include "G3D/Any.h"
namespace G3D {
-/**
- Sets a field on four vertices. Used by the constructor.
- */
-#define setMany(i0, i1, i2, i3, field, extreme) \
- _corner[i0].field = _corner[i1].field = \
- _corner[i2].field = _corner[i3].field = \
- (extreme).field
-
-Box::Box() {
+Box::Box() : _area(0), _volume(0) {
+}
+
+
+Box::Box
+ (const Point3& min,
+ const Point3& max) {
+ init(min.min(max), min.max(max));
+}
+
+
+Box::Box(const Point3& min) {
+ init(min, min);
+}
+
+
+Box::Box
+ (const Point3& min,
+ const Point3& max,
+ const CFrame& c) {
+ init(min.min(max), min.max(max));
+ *this = c.toWorldSpace(*this);
}
Box::Box(const AABox& b) {
+ debugAssert(! b.isEmpty());
init(b.low(), b.high());
}
-Box::Box(class BinaryInput& b) {
- deserialize(b);
+
+Box::Box(BinaryInput& b) {
+ deserialize(b);
}
-void Box::serialize(class BinaryOutput& b) const {
- int i;
- for (i = 0; i < 8; ++i) {
- _corner[i].serialize(b);
- }
+Box::Box(const Any& a) {
+ if (a.name() == "Box::inf") {
+ *this = Box::inf();
+ } else {
+ a.verifyName("Box", "AABox", "Point3");
+
+ if (a.name() == "Point3") {
+ *this = Box(Point3(a));
+ } else if (a.size() == 1) {
+ // Single point
+ *this = Box(Point3(a[0]));
+ } else if (a.size() == 2) {
+ *this = Box(Point3(a[0]), Point3(a[1]));
+ } else {
+ // Oriented box
+ a.verifySize(2);
+ a.verifyName("Box");
+ *this = Box(Point3(a[0]), Point3(a[1]), CFrame(a[2]));
+ }
+ }
+}
+
- // Other state can be reconstructed
+Any Box::toAny() const {
+ if (! isFinite()) {
+ return Any(Any::ARRAY, "Box::inf");
+ } else {
+ CFrame c;
+ getLocalFrame(c);
+ if (c.rotation == Matrix3::identity()) {
+ // Aligned box
+ AABox b;
+ getBounds(b);
+ return b.toAny();
+ } else {
+ // Oriented box
+ Any a(Any::ARRAY, "Box");
+
+ AABox b;
+ c.toObjectSpace(*this).getBounds(b);
+ a.append(b.low(), b.high(), c);
+ return a;
+ }
+ }
}
-void Box::deserialize(class BinaryInput& b) {
- int i;
+Box Box::operator*(float f) const {
+ Box b;
+
+ for (int i = 0; i < 3; ++i) {
+ b._edgeVector[i] = _edgeVector[i] * f;
+ b._center = _center * f;
+ b._area = _area * square(f * f);
+ b._volume = _area * (f * f * f);
+ }
- _center = Vector3::zero();
- for (i = 0; i < 8; ++i) {
- _corner[i].deserialize(b);
- _center += _corner[i];
- }
+ return b;
+}
- _center = _center / 8;
-
- // Reconstruct other state from the corners
- _axis[0] = _corner[5] - _corner[4];
- _axis[1] = _corner[7] - _corner[4];
- _axis[2] = _corner[0] - _corner[4];
+void Box::serialize(BinaryOutput& b) const {
+ int i;
for (i = 0; i < 3; ++i) {
- _extent[i] = _axis[i].magnitude();
- _axis[i] /= _extent[i];
+ _edgeVector[i].serialize(b);
}
+ _center.serialize(b);
- _volume = _extent.x * _extent.y * _extent.z;
-
- _area = 2 *
- (_extent.x * _extent.y +
- _extent.y * _extent.z +
- _extent.z * _extent.x);
+ // Other state can be reconstructed
}
-Box::Box(
- const Vector3& min,
- const Vector3& max) {
+void Box::deserialize(class BinaryInput& b) {
+ int i;
+ for (i = 0; i < 3; ++i) {
+ _edgeVector[i].deserialize(b);
+ }
+ _center.deserialize(b);
- init(min.min(max), min.max(max));
+ float extent0 = extent(0);
+ float extent1 = extent(1);
+ float extent2 = extent(2);
+ _volume = extent0 * extent1 * extent2;
+ _area = 2 *
+ (extent0 * extent1 +
+ extent1 * extent2 +
+ extent2 * extent0);
}
-void Box::init(
- const Vector3& min,
- const Vector3& max) {
+
+void Box::init
+ (const Point3& min,
+ const Point3& max) {
debugAssert(
(min.x <= max.x) &&
(min.y <= max.y) &&
(min.z <= max.z));
- setMany(0, 1, 2, 3, z, max);
- setMany(4, 5, 6, 7, z, min);
-
- setMany(1, 2, 5, 6, x, max);
- setMany(0, 3, 4, 7, x, min);
-
- setMany(3, 2, 6, 7, y, max);
- setMany(0, 1, 5, 4, y, min);
+ _center = (max + min) * 0.5f;
- _extent = max - min;
+ Vector3 bounds = Vector3(max.x - min.x, max.y - min.y, max.z - min.z);
+ _edgeVector[0] = Vector3(bounds.x, 0, 0);
+ _edgeVector[1] = Vector3(0, bounds.y, 0);
+ _edgeVector[2] = Vector3(0, 0, bounds.z);
+ bool finiteExtent = true;
+
+ for (int i = 0; i < 3; ++i) {
+ if (! G3D::isFinite(extent(i))) {
+ finiteExtent = false;
+ // If the extent is infinite along an axis, make the center zero to avoid NaNs
+ _center[i] = 0.0f;
+ }
+ }
- _axis[0] = Vector3::unitX();
- _axis[1] = Vector3::unitY();
- _axis[2] = Vector3::unitZ();
- if (_extent.isFinite()) {
- _volume = _extent.x * _extent.y * _extent.z;
+ if (finiteExtent) {
+ _volume = bounds.x * bounds.y * bounds.z;
} else {
_volume = G3D::finf();
}
- debugAssert(! isNaN(_extent.x));
+ debugAssert(! _edgeVector[0].isNaN());
_area = 2 *
- (_extent.x * _extent.y +
- _extent.y * _extent.z +
- _extent.z * _extent.x);
+ (bounds.x * bounds.y +
+ bounds.y * bounds.z +
+ bounds.z * bounds.x);
+}
- _center = (max + min) * 0.5f;
- // If the extent is infinite along an axis, make the center zero to avoid NaNs
- for (int i = 0; i < 3; ++i) {
- if (! G3D::isFinite(_extent[i])) {
- _center[i] = 0.0f;
- }
+Vector3 Box::corner(int i) const{
+ debugAssert(i < 8);
+ // The corner forms a bit mask (xyz), where a one indicates we should
+ // add half of the corresponding edge vector from center, and a zero indicates
+ // we should subtract it. Note:
+ // 1 = 001
+ // 2 = 010
+ // 4 = 100
+ //
+ // The following bit-hacky code shows this directly:
+ // return _center + ((_edgeVector[0] * ((i&1) - 0.5) +
+ // _edgeVector[1] * (((i>>1)&1) - 0.5) +
+ // _edgeVector[2] * (((i>>2)&1) - 0.5)));
+ // This method is implemented as a swtich statement due to being marginally faster than the bit-hack method
+ // Also, the _center + 0.5f * (...) is repeated every time for similarly speed-based reasons.
+ switch(i) {
+ case 0: return _center + (0.5f * (-_edgeVector[0] - _edgeVector[1] - _edgeVector[2]));
+ case 1: return _center + (0.5f * ( _edgeVector[0] - _edgeVector[1] - _edgeVector[2]));
+ case 2: return _center + (0.5f * (-_edgeVector[0] + _edgeVector[1] - _edgeVector[2]));
+ case 3: return _center + (0.5f * ( _edgeVector[0] + _edgeVector[1] - _edgeVector[2]));
+ case 4: return _center + (0.5f * (-_edgeVector[0] - _edgeVector[1] + _edgeVector[2]));
+ case 5: return _center + (0.5f * ( _edgeVector[0] - _edgeVector[1] + _edgeVector[2]));
+ case 6: return _center + (0.5f * (-_edgeVector[0] + _edgeVector[1] + _edgeVector[2]));
+ default: return _center + (0.5f * ( _edgeVector[0] + _edgeVector[1] + _edgeVector[2]));//case 7
}
+
}
-
float Box::volume() const {
return _volume;
}
@@ -144,11 +225,14 @@ float Box::area() const {
void Box::getLocalFrame(CoordinateFrame& frame) const {
+ const Vector3& axis0 = axis(0);
+ const Vector3& axis1 = axis(1);
+ const Vector3& axis2 = axis(2);
frame.rotation = Matrix3(
- _axis[0][0], _axis[1][0], _axis[2][0],
- _axis[0][1], _axis[1][1], _axis[2][1],
- _axis[0][2], _axis[1][2], _axis[2][2]);
+ axis0[0], axis1[0], axis2[0],
+ axis0[1], axis1[1], axis2[1],
+ axis0[2], axis1[2], axis2[2]);
frame.translation = _center;
}
@@ -161,30 +245,30 @@ CoordinateFrame Box::localFrame() const {
}
-void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3& v3) const {
+void Box::getFaceCorners(int f, Point3& v0, Point3& v1, Point3& v2, Point3& v3) const {
switch (f) {
case 0:
- v0 = _corner[0]; v1 = _corner[1]; v2 = _corner[2]; v3 = _corner[3];
+ v0 = corner(0); v1 = corner(2); v2 = corner(3); v3 = corner(1);
break;
case 1:
- v0 = _corner[1]; v1 = _corner[5]; v2 = _corner[6]; v3 = _corner[2];
+ v0 = corner(1); v1 = corner(3); v2 = corner(7); v3 = corner(5);
break;
case 2:
- v0 = _corner[7]; v1 = _corner[6]; v2 = _corner[5]; v3 = _corner[4];
+ v0 = corner(6); v1 = corner(4); v2 = corner(5); v3 = corner(7);
break;
case 3:
- v0 = _corner[2]; v1 = _corner[6]; v2 = _corner[7]; v3 = _corner[3];
+ v0 = corner(3); v1 = corner(2); v2 = corner(6); v3 = corner(7);
break;
case 4:
- v0 = _corner[3]; v1 = _corner[7]; v2 = _corner[4]; v3 = _corner[0];
+ v0 = corner(2); v1 = corner(0); v2 = corner(4); v3 = corner(6);
break;
case 5:
- v0 = _corner[1]; v1 = _corner[0]; v2 = _corner[4]; v3 = _corner[5];
+ v0 = corner(1); v1 = corner(5); v2 = corner(4); v3 = corner(0);
break;
default:
@@ -196,8 +280,8 @@ void Box::getFaceCorners(int f, Vector3& v0, Vector3& v1, Vector3& v2, Vector3&
int Box::dummy = 0;
-bool Box::culledBy(
- const Array<Plane>& plane,
+bool Box::culledBy
+ (const Array<Plane>& plane,
int& cullingPlane,
const uint32 _inMask,
uint32& childMask) const {
@@ -208,13 +292,11 @@ bool Box::culledBy(
childMask = 0;
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- Vector3 corner;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
int numContained = 0;
int v = 0;
@@ -222,93 +304,94 @@ bool Box::culledBy(
// We can early-out only if we have found one point on each
// side of the plane (i.e. if we are straddling). That
// occurs when (numContained < v) && (numContained > 0)
- for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
- if (plane[p].halfSpaceContains(_corner[v])) {
+ for (v = 0; (v < 8) && ((numContained == v) || (numContained == 0)); ++v) {
+ if (plane[p].halfSpaceContains(corner(v))) {
++numContained;
}
- }
+ }
- if (numContained == 0) {
- // Plane p culled the box
- cullingPlane = p;
+ if (numContained == 0) {
+ // Plane p culled the box
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (numContained < v) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
-bool Box::culledBy(
- const Array<Plane>& plane,
- int& cullingPlane,
- const uint32 _inMask) const {
+bool Box::culledBy
+ (const Array<Plane>& plane,
+ int& cullingPlane,
+ const uint32 _inMask) const {
- uint32 inMask = _inMask;
- assert(plane.size() < 31);
+ uint32 inMask = _inMask;
+ assert(plane.size() < 31);
// See if there is one plane for which all of the
- // vertices are in the negative half space.
+ // vertices are in the negative half space.
for (int p = 0; p < plane.size(); ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
- bool culled = true;
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
+ bool culled = true;
int v;
- // Assume this plane culls all points. See if there is a point
- // not culled by the plane... early out when at least one point
+ // Assume this plane culls all points. See if there is a point
+ // not culled by the plane... early out when at least one point
// is in the positive half space.
- for (v = 0; (v < 8) && culled; ++v) {
+ for (v = 0; (v < 8) && culled; ++v) {
culled = ! plane[p].halfSpaceContains(corner(v));
- }
+ }
- if (culled) {
- // Plane p culled the box
- cullingPlane = p;
+ if (culled) {
+ // Plane p culled the box
+ cullingPlane = p;
- return true;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
-bool Box::contains(
- const Vector3& point) const {
+bool Box::contains
+ (const Point3& point) const {
// Form axes from three edges, transform the point into that
// space, and perform 3 interval tests
-
- Vector3 u = _corner[4] - _corner[0];
- Vector3 v = _corner[3] - _corner[0];
- Vector3 w = _corner[1] - _corner[0];
+ // TODO: Write in a more intuitive way. I left it as it was before after figuring it out, but
+ // this should make no sense to someone who is just starting to read this code.
+ const Vector3& u = _edgeVector[2];
+ const Vector3& v = _edgeVector[1];
+ const Vector3& w = _edgeVector[0];
Matrix3 M = Matrix3(u.x, v.x, w.x,
u.y, v.y, w.y,
@@ -316,7 +399,7 @@ bool Box::contains(
// M^-1 * (point - _corner[0]) = point in unit cube's object space
// compute the inverse of M
- Vector3 osPoint = M.inverse() * (point - _corner[0]);
+ Vector3 osPoint = M.inverse() * (point - corner(0));
return
(osPoint.x >= 0) &&
@@ -327,13 +410,13 @@ bool Box::contains(
(osPoint.z <= 1);
}
-#undef setMany
+
void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
- float aXY = _extent.x * _extent.y;
- float aYZ = _extent.y * _extent.z;
- float aZX = _extent.z * _extent.x;
+ float aXY = extent(0) * extent(1);
+ float aYZ = extent(1) * extent(2);
+ float aZX = extent(2) * extent(0);
float r = (float)uniformRandom(0, aXY + aYZ + aZX);
@@ -343,20 +426,20 @@ void Box::getRandomSurfacePoint(Vector3& P, Vector3& N) const {
// The probability of choosing a given face is proportional to
// its area.
if (r < aXY) {
- P = _axis[0] * (float)uniformRandom(-0.5, 0.5) * _extent.x +
- _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
- _center + _axis[2] * d * _extent.z * 0.5f;
- N = _axis[2] * d;
+ P = _edgeVector[0] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[1] * (float)uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[2] * d * 0.5f;
+ N = axis(2) * d;
} else if (r < aYZ) {
- P = _axis[1] * (float)uniformRandom(-0.5, 0.5) * _extent.y +
- _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
- _center + _axis[0] * d * _extent.x * 0.5f;
- N = _axis[0] * d;
+ P = _edgeVector[1] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[2] * (float)uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[0] * d * 0.5f;
+ N = axis(0) * d;
} else {
- P = _axis[2] * (float)uniformRandom(-0.5, 0.5) * _extent.z +
- _axis[0] *(float) uniformRandom(-0.5, 0.5) * _extent.x +
- _center + _axis[1] * d * _extent.y * 0.5f;
- N = _axis[1] * d;
+ P = _edgeVector[2] * (float)uniformRandom(-0.5, 0.5) +
+ _edgeVector[0] *(float) uniformRandom(-0.5, 0.5) +
+ _center + _edgeVector[1] * d * 0.5f;
+ N = axis(1) * d;
}
}
@@ -365,28 +448,25 @@ Vector3 Box::randomInteriorPoint() const {
Vector3 sum = _center;
for (int a = 0; a < 3; ++a) {
- sum += _axis[a] * (float)uniformRandom(-0.5, 0.5) * _extent[a];
+ sum += _edgeVector[a] * (float)uniformRandom(-0.5, 0.5);
}
return sum;
}
+
Box Box::inf() {
return Box(-Vector3::inf(), Vector3::inf());
}
-void Box::getBounds(class AABox& aabb) const {
-
- Vector3 lo = _corner[0];
- Vector3 hi = lo;
- for (int v = 1; v < 8; ++v) {
- const Vector3& C = _corner[v];
- lo = lo.min(C);
- hi = hi.max(C);
+void Box::getBounds(AABox& aabb) const {
+ debugAssert(! _edgeVector[0].isNaN());
+ debugAssert(! _center.isNaN());
+ aabb = AABox::empty();
+ for (int i = 0; i < 8; ++i) {
+ aabb.merge(corner(i));
}
-
- aabb = AABox(lo, hi);
}
diff --git a/dep/g3dlite/source/BumpMapPreprocess.cpp b/dep/g3dlite/source/BumpMapPreprocess.cpp
index 20281caf8cb..df5a23c13a6 100644
--- a/dep/g3dlite/source/BumpMapPreprocess.cpp
+++ b/dep/g3dlite/source/BumpMapPreprocess.cpp
@@ -6,7 +6,7 @@
\created 2010-01-28
\edited 2010-01-28
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#include "G3D/BumpMapPreprocess.h"
@@ -17,7 +17,7 @@ namespace G3D {
BumpMapPreprocess::BumpMapPreprocess(const Any& any) {
*this = BumpMapPreprocess();
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "lowpassfilter") {
lowPassFilter = it->value;
@@ -32,7 +32,7 @@ BumpMapPreprocess::BumpMapPreprocess(const Any& any) {
}
-BumpMapPreprocess::operator Any() const {
+Any BumpMapPreprocess::toAny() const {
Any any(Any::TABLE, "BumpMapPreprocess");
any["lowPassFilter"] = lowPassFilter;
any["zExtentPixels"] = zExtentPixels;
diff --git a/dep/g3dlite/source/Capsule.cpp b/dep/g3dlite/source/Capsule.cpp
index 2ad3891c960..14df8d31b9e 100644
--- a/dep/g3dlite/source/Capsule.cpp
+++ b/dep/g3dlite/source/Capsule.cpp
@@ -22,7 +22,7 @@
namespace G3D {
Capsule::Capsule(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
@@ -31,47 +31,47 @@ Capsule::Capsule() {
Capsule::Capsule(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), _radius(_r) {
+ : p1(_p1), p2(_p2), _radius(_r) {
}
void Capsule::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(_radius);
+ p1.serialize(b);
+ p2.serialize(b);
+ b.writeFloat64(_radius);
}
void Capsule::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- _radius = b.readFloat64();
+ p1.deserialize(b);
+ p2.deserialize(b);
+ _radius = (float)b.readFloat64();
}
Line Capsule::axis() const {
- return Line::fromTwoPoints(p1, p2);
+ return Line::fromTwoPoints(p1, p2);
}
float Capsule::volume() const {
- return
- // Sphere volume
- pow(_radius, 3) * pi() * 4 / 3 +
+ return
+ // Sphere volume
+ pow(_radius, 3) * (float)pi() * 4 / 3 +
- // Cylinder volume
- pow(_radius, 2) * (p1 - p2).magnitude();
+ // Cylinder volume
+ pow(_radius, 2) * (p1 - p2).magnitude();
}
float Capsule::area() const {
- return
- // Sphere area
- pow(_radius, 2) * 4 * pi() +
+ return
+ // Sphere area
+ pow(_radius, 2) * 4 * (float)pi() +
- // Cylinder area
- twoPi() * _radius * (p1 - p2).magnitude();
+ // Cylinder area
+ (float)twoPi() * _radius * (p1 - p2).magnitude();
}
@@ -147,10 +147,10 @@ Vector3 Capsule::randomInteriorPoint() const {
Vector3 p;
- float hemiVolume = pi() * (r*r*r) * 4 / 6.0;
- float cylVolume = pi() * square(r) * h;
+ float hemiVolume = (float)pi() * (r*r*r) * 4 / 6.0f;
+ float cylVolume = (float)pi() * square(r) * h;
- float r1 = uniformRandom(0, 2.0 * hemiVolume + cylVolume);
+ float r1 = uniformRandom(0, 2.0f * hemiVolume + cylVolume);
if (r1 < 2.0 * hemiVolume) {
diff --git a/dep/g3dlite/source/CollisionDetection.cpp b/dep/g3dlite/source/CollisionDetection.cpp
index 77eef0a5500..ef48a5bb98f 100644
--- a/dep/g3dlite/source/CollisionDetection.cpp
+++ b/dep/g3dlite/source/CollisionDetection.cpp
@@ -37,7 +37,7 @@
namespace G3D {
bool CollisionDetection::ignoreBool;
-Vector3 CollisionDetection::ignore;
+Vector3 CollisionDetection::ignore;
Array<Vector3> CollisionDetection::ignoreArray;
@@ -186,7 +186,7 @@ bool CollisionDetection::parallelAxisForSolidBoxSolidBox(
int & axis1,
int & axis2) {
const double parallelDot = 1.0 - epsilon;
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; ++i) {
if (ca[i] >= parallelDot) {
axis1 = i / 3;
axis2 = i % 3;
@@ -221,14 +221,14 @@ void CollisionDetection::fillSolidBoxSolidBoxInfo(
// corresponds to c[row * 3 + col] for this 9 element array.
//
// c[] holds signed values, ca[] hold absolute values
- for (int i = 0; i < 9; i++) {
+ for (int i = 0; i < 9; ++i) {
c[i] = dot(box1.axis(i / 3), box2.axis(i % 3));
ca[i] = fabs(c[i]);
}
// store all possible dot products between the axes of box1 and D,
// as well as the axes of box2 and D
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; ++i) {
ad[i] = dot(box1.axis(i), D);
bd[i] = dot(box2.axis(i), D);
}
@@ -251,7 +251,7 @@ bool CollisionDetection::conservativeBoxBoxTest(
bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(
const Box& box1,
const Box& box2,
- const int lastSeparatingAxis) {
+ const int lastSeparatingAxis) {
// for explanations of the variable please refer to the
// paper and fillSolidBoxSolidBoxInfo()
Vector3 a;
@@ -285,7 +285,7 @@ bool CollisionDetection::fixedSolidBoxIntersectsFixedSolidBox(
// any of the three axes of box1, any of the three axes of box2,
// or any of the 9 possible cross products of axes from box1
// and box2
- for (int i = 0; i < 15; i++) {
+ for (int i = 0; i < 15; ++i) {
// do not need to check edge-edge cases if any two of
// the axes are parallel
if (parallelAxes && i == 6) {
@@ -388,10 +388,10 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// test if the boxes can be separated by a plane normal to
// any of the three axes of box1, any of the three axes of box2,
// (test 9 possible cross products later)
- float penetration = -finf();
+ float penetration = -finf();
int penetrationAxisIndex = -1;
- for (int i = 0; i < 6; i++) {
+ for (int i = 0; i < 6; ++i) {
float projectedDistance =
projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
@@ -411,44 +411,45 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// for each edge-edge case we have to adjust the magnitude of
// penetration since we did not include the dot(L, L) denominator
// that can be smaller than 1.0 for the edge-edge cases.
- if (!parallelAxes) {
- double edgeDistances[9];
-
- // run through edge-edge cases to see if we can find a separating axis
- for (int i = 6; i < 15; i++) {
- float projectedDistance =
- projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
-
- // found a separating axis, the boxes do not intersect,
- // correct magnitude and return projected distance
- if (projectedDistance > 0.0) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- return -projectedDistance;
- }
-
- edgeDistances[i - 6] = projectedDistance;
- }
-
- // no separating axis found, the boxes do intersect,
- // correct the magnitudes of the projectedDistance values
- for (int i = 6; i < 15; i++) {
- // find the negative penetration value with the smallest magnitude,
- // the adjustment done for the edge-edge cases only increases
- // magnitude by dividing by a number smaller than 1 and greater than 0
- float projectedDistance = (float)edgeDistances[i - 6];
- if (projectedDistance > penetration) {
- Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
- projectedDistance /= dot(L, L);
- if (projectedDistance > penetration) {
- penetration = projectedDistance;
- penetrationAxisIndex = i;
- }
- }
- }
- }
-
- // get final separating axis vector
+
+ if (!parallelAxes) {
+ double edgeDistances[9];
+
+ // run through edge-edge cases to see if we can find a separating axis
+ for (int i = 6; i < 15; ++i) {
+ float projectedDistance =
+ projectedDistanceForSolidBoxSolidBox(i, a, b, D, c, ca, ad, bd);
+
+ // found a separating axis, the boxes do not intersect,
+ // correct magnitude and return projected distance
+ if (projectedDistance > 0.0) {
+ Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
+ projectedDistance /= dot(L, L);
+ return -projectedDistance;
+ }
+
+ edgeDistances[i - 6] = projectedDistance;
+ }
+
+ // no separating axis found, the boxes do intersect,
+ // correct the magnitudes of the projectedDistance values
+ for (int i = 6; i < 15; ++i) {
+ // find the negative penetration value with the smallest magnitude,
+ // the adjustment done for the edge-edge cases only increases
+ // magnitude by dividing by a number smaller than 1 and greater than 0
+ float projectedDistance = (float)edgeDistances[i - 6];
+ if (projectedDistance > penetration) {
+ Vector3 L = separatingAxisForSolidBoxSolidBox(i, box1, box2);
+ projectedDistance /= dot(L, L);
+ if (projectedDistance > penetration) {
+ penetration = projectedDistance;
+ penetrationAxisIndex = i;
+ }
+ }
+ }
+ }
+
+ // get final separating axis vector
Vector3 L = separatingAxisForSolidBoxSolidBox(penetrationAxisIndex,
box1, box2);
@@ -462,18 +463,15 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
if (penetrationAxisIndex < 6) {
// vertex to face collision, find deepest colliding vertex
const Box* vertexBox;
- const Box* faceBox;
Vector3 faceNormal = L;
// L will be the outward facing normal for the faceBox
if (penetrationAxisIndex < 3) {
- faceBox = & box1;
vertexBox = & box2;
if (dot(L, D) < 0) {
faceNormal = -L;
}
} else {
- faceBox = & box2;
vertexBox = & box1;
if (dot(L, D) > 0) {
faceNormal = -L;
@@ -484,7 +482,7 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// face normal direction
int deepestPointIndex = 0;
float deepestPointDot = dot(faceNormal, vertexBox->corner(0));
- for (int i = 1; i < 8; i++) {
+ for (int i = 1; i < 8; ++i) {
float dotProduct = dot(faceNormal, vertexBox->corner(i));
if (dotProduct < deepestPointDot) {
deepestPointDot = dotProduct;
@@ -507,7 +505,7 @@ float CollisionDetection::penetrationDepthForFixedBoxFixedBox(
// find edge line by finding the edge axis, and the
// other two axes that are closest to the other box
- for (int i = 0; i < 3; i++ ) {
+ for (int i = 0; i < 3; ++i) {
if (i == edge1) {
lineDir1 = box1.axis(i);
} else {
@@ -854,27 +852,27 @@ float CollisionDetection::collisionTimeForMovingPointFixedPlane(
Vector3& outNormal) {
// Solve for the time at which normal.dot(point + velocity) + d == 0.
- double d;
+ float d;
Vector3 normal;
plane.getEquation(normal, d);
- float vdotN = velocity.dot(normal);
- float pdotN = point.dot(normal);
+ const float vdotN = velocity.dot(normal);
+ const float pdotN = point.dot(normal);
- if (fuzzyEq(pdotN + d, 0)) {
+ if (fuzzyEq(pdotN + d, 0.0f)) {
// The point is *in* the plane.
location = point;
outNormal = normal;
return 0;
}
- if (vdotN >= 0) {
+ if (vdotN >= 0.0f) {
// no collision will occur
location = Vector3::inf();
return finf();
}
- float t = -(pdotN + d) / vdotN;
+ const float t = -(pdotN + d) / vdotN;
if (t < 0) {
location = Vector3::inf();
return finf();
@@ -921,7 +919,7 @@ bool __fastcall CollisionDetection::rayAABox(
// Find candidate planes.
for (int i = 0; i < 3; ++i) {
if (ray.origin()[i] < MinB[i]) {
- location[i] = MinB[i];
+ location[i] = MinB[i];
inside = false;
// Calculate T distances to candidate planes
@@ -929,7 +927,7 @@ bool __fastcall CollisionDetection::rayAABox(
MaxT[i] = (MinB[i] - ray.origin()[i]) * invDir[i];
}
} else if (ray.origin()[i] > MaxB[i]) {
- location[i] = MaxB[i];
+ location[i] = MaxB[i];
inside = false;
// Calculate T distances to candidate planes
@@ -940,7 +938,7 @@ bool __fastcall CollisionDetection::rayAABox(
}
if (inside) {
- // Ray origin inside bounding box
+ // Ray origin inside bounding box
location = ray.origin();
return true;
}
@@ -1065,10 +1063,10 @@ float CollisionDetection::collisionTimeForMovingSphereFixedSphere(
/*
float CollisionDetection::collisionTimeForMovingPointFixedTriangle(
- const Vector3& point,
- const Vector3& velocity,
+ const Vector3& point,
+ const Vector3& velocity,
const Triangle& triangle,
- Vector3& outLocation,
+ Vector3& outLocation,
Vector3& outNormal) {
double time = collisionTimeForMovingPointFixedPlane(point, velocity, triangle.plane(), outLocation, outNormal);
@@ -1234,73 +1232,73 @@ bool CollisionDetection::collisionLocationForMovingPointFixedAABox(
Vector3& normal) {
// Integer representation of a floating-point value.
- #define IR(x) ((uint32&)x)
+ #define IR(x) ((uint32&)x)
Inside = true;
- const Vector3& MinB = box.low();
- const Vector3& MaxB = box.high();
- Vector3 MaxT(-1.0f, -1.0f, -1.0f);
+ const Vector3& MinB = box.low();
+ const Vector3& MaxB = box.high();
+ Vector3 MaxT(-1.0f, -1.0f, -1.0f);
- // Find candidate planes.
+ // Find candidate planes.
for (int i = 0; i < 3; ++i) {
- if (origin[i] < MinB[i]) {
- location[i] = MinB[i];
- Inside = false;
+ if (origin[i] < MinB[i]) {
+ location[i] = MinB[i];
+ Inside = false;
- // Calculate T distances to candidate planes
+ // Calculate T distances to candidate planes
if (IR(dir[i])) {
MaxT[i] = (MinB[i] - origin[i]) / dir[i];
}
} else if (origin[i] > MaxB[i]) {
- location[i] = MaxB[i];
- Inside = false;
+ location[i] = MaxB[i];
+ Inside = false;
- // Calculate T distances to candidate planes
+ // Calculate T distances to candidate planes
if (IR(dir[i])) {
MaxT[i] = (MaxB[i] - origin[i]) / dir[i];
}
- }
- }
+ }
+ }
- if (Inside) {
- // Ray origin inside bounding box
+ if (Inside) {
+ // Ray origin inside bounding box
location = origin;
- return false;
- }
+ return false;
+ }
- // Get largest of the maxT's for final choice of intersection
- int WhichPlane = 0;
- if (MaxT[1] > MaxT[WhichPlane]) {
+ // Get largest of the maxT's for final choice of intersection
+ int WhichPlane = 0;
+ if (MaxT[1] > MaxT[WhichPlane]) {
WhichPlane = 1;
}
- if (MaxT[2] > MaxT[WhichPlane]) {
+ if (MaxT[2] > MaxT[WhichPlane]) {
WhichPlane = 2;
}
- // Check final candidate actually inside box
+ // Check final candidate actually inside box
if (IR(MaxT[WhichPlane]) & 0x80000000) {
// Miss the box
return false;
}
- for (int i = 0; i < 3; ++i) {
+ for (int i = 0; i < 3; ++i) {
if (i != WhichPlane) {
- location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
+ location[i] = origin[i] + MaxT[WhichPlane] * dir[i];
if ((location[i] < MinB[i]) ||
(location[i] > MaxB[i])) {
// On this plane we're outside the box extents, so
// we miss the box
return false;
}
- }
- }
+ }
+ }
// Choose the normal to be the plane normal facing into the ray
normal = Vector3::zero();
normal[WhichPlane] = (dir[WhichPlane] > 0) ? -1.0 : 1.0;
- return true;
+ return true;
#undef IR
}
@@ -1338,19 +1336,24 @@ float CollisionDetection::collisionTimeForMovingPointFixedRectangle(
/** Used by findRayCapsuleIntersection.
@cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp */
static int findRayCapsuleIntersectionAux(
- const Vector3& rkOrigin,
- const Vector3& rkDirection,
- const Capsule& rkCapsule,
- double afT[2]) {
+ const Vector3& rkOrigin,
+ const Vector3& rkDirection,
+ const Capsule& rkCapsule,
+ double afT[2]) {
- Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0);
+ Vector3 capsuleDirection = rkCapsule.point(1) - rkCapsule.point(0);
// set up quadratic Q(t) = a*t^2 + 2*b*t + c
- Vector3 kU, kV, kW = capsuleDirection;
- float fWLength = kW.unitize();
- Vector3::generateOrthonormalBasis(kU, kV, kW);
+ Vector3 kW = capsuleDirection;
+ float fWLength = kW.length();
+ kW = kW.direction();
+
+ Vector3 kU, kV;
+ kW.getTangents(kU, kV);
Vector3 kD(kU.dot(rkDirection), kV.dot(rkDirection), kW.dot(rkDirection));
- float fDLength = kD.unitize();
+
+ float fDLength = kD.length();
+ kD = kD.direction();
float fEpsilon = 1e-6f;
@@ -1405,15 +1408,15 @@ static int findRayCapsuleIntersectionAux(
fTmp = kP.z + fT*kD.z;
if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
afT[iQuantity] = fT * fInvDLength;
- iQuantity++;
- }
+ ++iQuantity;
+ }
fT = (-fB + fRoot)*fInv;
fTmp = kP.z + fT*kD.z;
- if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
+ if ((0.0f <= fTmp) && (fTmp <= fWLength)) {
afT[iQuantity++] = fT*fInvDLength;
- }
+ }
if (iQuantity == 2) {
// line intersects capsule wall in two places
@@ -1442,7 +1445,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
fT = -fB + fRoot;
@@ -1451,7 +1454,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
} else if (fDiscr == 0.0f) {
fT = -fB;
@@ -1460,7 +1463,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
}
@@ -1478,7 +1481,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
fT = -fB + fRoot;
@@ -1487,7 +1490,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
} else if (fDiscr == 0.0f) {
fT = -fB;
@@ -1496,7 +1499,7 @@ static int findRayCapsuleIntersectionAux(
afT[iQuantity++] = fT*fInvDLength;
if (iQuantity == 2) {
return 2;
- }
+ }
}
}
@@ -1506,25 +1509,25 @@ static int findRayCapsuleIntersectionAux(
/** Used by collisionTimeForMovingPointFixedCapsule.
@cite From magic software http://www.magic-software.com/Source/Intersection3D/MgcIntr3DLinCap.cpp
-
- @param rkRay The ray
- @param rkCapsule The capsule
- @param riQuantity The number of intersections found
- @param akPoint The intersections found
- @return True if there is at least one intersection
- */
+
+ @param rkRay The ray
+ @param rkCapsule The capsule
+ @param riQuantity The number of intersections found
+ @param akPoint The intersections found
+ @return True if there is at least one intersection
+ */
static bool findRayCapsuleIntersection(
- const Ray& rkRay,
- const Capsule& rkCapsule,
- int& riQuantity,
- Vector3 akPoint[2]) {
+ const Ray& rkRay,
+ const Capsule& rkCapsule,
+ int& riQuantity,
+ Vector3 akPoint[2]) {
double afT[2];
riQuantity = findRayCapsuleIntersectionAux(rkRay.origin(), rkRay.direction(), rkCapsule, afT);
// Only return intersections that occur in the future
int iClipQuantity = 0;
- int i;
+ int i;
for (i = 0; i < riQuantity; ++i) {
if (afT[i] >= 0.0f) {
akPoint[iClipQuantity] = rkRay.origin() + afT[i] * rkRay.direction();
@@ -1537,30 +1540,30 @@ static bool findRayCapsuleIntersection(
}
float CollisionDetection::collisionTimeForMovingPointFixedCapsule(
- const Vector3& _point,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
+ const Vector3& _point,
+ const Vector3& velocity,
+ const Capsule& capsule,
+ Vector3& location,
Vector3& outNormal) {
- float timeScale = velocity.magnitude();
+ float timeScale = velocity.magnitude();
if (timeScale == 0.0f) {
timeScale = 1;
}
- Vector3 direction = velocity / timeScale;
- int numIntersections;
- Vector3 intersection[2];
- findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection);
+ Vector3 direction = velocity / timeScale;
+ int numIntersections;
+ Vector3 intersection[2];
+ findRayCapsuleIntersection(Ray::fromOriginAndDirection(_point, direction), capsule, numIntersections, intersection);
- if (numIntersections == 2) {
- // A collision can only occur if there are two intersections. If there is one
- // intersection, that one is exiting the capsule.
+ if (numIntersections == 2) {
+ // A collision can only occur if there are two intersections. If there is one
+ // intersection, that one is exiting the capsule.
- // Find the entering intersection (the first one that occurs).
- float d0 = (intersection[0] - _point).squaredMagnitude();
- float d1 = (intersection[1] - _point).squaredMagnitude();
+ // Find the entering intersection (the first one that occurs).
+ float d0 = (intersection[0] - _point).squaredMagnitude();
+ float d1 = (intersection[1] - _point).squaredMagnitude();
// Compute the surface normal (if we aren't ignoring the result)
if (&outNormal != &ignore) {
@@ -1569,40 +1572,41 @@ float CollisionDetection::collisionTimeForMovingPointFixedCapsule(
}
if (d0 > d1) {
- location = intersection[1];
- return sqrt(d1) / timeScale;
- } else {
- location = intersection[0];
- return sqrt(d0) / timeScale;
- }
- } else {
- // No entering intersection discovered; return no intersection.
- location = Vector3::inf();
- return finf();
- }
+ location = intersection[1];
+ return sqrt(d1) / timeScale;
+ } else {
+ location = intersection[0];
+ return sqrt(d0) / timeScale;
+ }
+ } else {
+ // No entering intersection discovered; return no intersection.
+ location = Vector3::inf();
+ return finf();
+ }
}
float CollisionDetection::collisionTimeForMovingSphereFixedPlane(
- const Sphere& sphere,
- const Vector3& velocity,
- const Plane& plane,
- Vector3& location,
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Plane& plane,
+ Vector3& location,
Vector3& outNormal) {
- if (sphere.radius == 0) {
- // Optimization for zero radius sphere
+ if (sphere.radius == 0) {
+ // Optimization for zero radius sphere
return collisionTimeForMovingPointFixedPlane(sphere.center, velocity, plane, location, outNormal);
- }
+ }
- // The collision point on the sphere will be the point at
- // center - (radius * normal). Collisions only occur when
+ // The world-space collision point, which lies on the surface of the sphere, will be the point at
+ // center + velocity * time - (radius * planeNormal). Collisions only occur when
// the sphere is travelling into the plane.
- double d;
+ float d;
plane.getEquation(outNormal, d);
- double vdotN = velocity.dot(outNormal);
+ // Rate at which the sphere is approaching the plane
+ const float vdotN = velocity.dot(outNormal);
if (fuzzyGt(vdotN, 0)) {
// No collision when the sphere is moving towards a backface.
@@ -1610,34 +1614,37 @@ float CollisionDetection::collisionTimeForMovingSphereFixedPlane(
return (float)finf();
}
- float cdotN = sphere.center.dot(outNormal);
-
- // Distance from the center to the plane
- float distance = cdotN + (float)d;
-
- // Where is the collision on the sphere?
- Vector3 point = sphere.center - (sphere.radius * outNormal);
+ // Initial distance from the sphere center to the plane
+ const float distance = sphere.center.dot(outNormal) + d;
if (fuzzyLe(G3D::abs(distance), sphere.radius)) {
// Already interpenetrating
location = sphere.center - distance * outNormal;
return 0;
} else {
+ // The point on the sphere (in world space) that will eventually first contact the plane
+ const Point3& point = sphere.center - (sphere.radius * outNormal);
+
+ // The problem is now reduced to finding when the point hits the plane
return collisionTimeForMovingPointFixedPlane(point, velocity, plane, location, outNormal);
}
}
-float CollisionDetection::collisionTimeForMovingSphereFixedTriangle(
- const class Sphere& sphere,
- const Vector3& velocity,
- const Triangle& triangle,
- Vector3& outLocation,
- float b[3]) {
+float CollisionDetection::collisionTimeForMovingSphereFixedTriangle
+(const Sphere& sphere,
+ const Vector3& velocity,
+ const Triangle& triangle,
+ Vector3& outLocation,
+ float b[3]) {
+ if (velocity.dot(triangle.normal()) > 0.0f) {
+ // No collision if moving towards a backface
+ return finf();
+ }
Vector3 dummy;
- float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(),
+ const float time = collisionTimeForMovingSphereFixedPlane(sphere, velocity, triangle.plane(),
outLocation, dummy);
if (time == finf()) {
@@ -1660,7 +1667,7 @@ float CollisionDetection::collisionTimeForMovingSphereFixedTriangle(
debugAssertM(b[0] >= 0.0 && b[0] <= 1.0f, "Intersection is outside triangle.");
debugAssertM(b[1] >= 0.0 && b[1] <= 1.0f, "Intersection is outside triangle.");
debugAssertM(b[2] >= 0.0 && b[2] <= 1.0f, "Intersection is outside triangle.");
- Vector3 blend =
+ const Vector3& blend =
b[0] * triangle.vertex(0) +
b[1] * triangle.vertex(1) +
b[2] * triangle.vertex(2);
@@ -1817,18 +1824,18 @@ float CollisionDetection::collisionTimeForMovingSphereFixedBox(
float CollisionDetection::collisionTimeForMovingSphereFixedCapsule(
- const Sphere& sphere,
- const Vector3& velocity,
- const Capsule& capsule,
- Vector3& location,
+ const Sphere& sphere,
+ const Vector3& velocity,
+ const Capsule& capsule,
+ Vector3& location,
Vector3& outNormal) {
(void)outNormal;
- Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius);
+ Capsule _capsule(capsule.point(0), capsule.point(1), capsule.radius() + sphere.radius);
Vector3 normal;
- double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal);
+ double time = collisionTimeForMovingPointFixedCapsule(sphere.center, velocity, _capsule, location, normal);
if (time < finf()) {
// Location is now the position of the center of the sphere at the time of collision.
@@ -1847,14 +1854,14 @@ Vector3 CollisionDetection::bounceDirection(
const Vector3& collisionLocation,
const Vector3& collisionNormal) {
- // Location when the collision occurs
+ // Location when the collision occurs
Vector3 sphereLocation = sphere.center + velocity * collisionTime;
Vector3 normal = (sphereLocation - collisionLocation);
if (fuzzyEq(normal.squaredMagnitude(), 0)) {
normal = collisionNormal;
} else {
- normal.unitize();
+ normal = normal.direction();
}
Vector3 direction = velocity.direction();
@@ -1926,10 +1933,10 @@ Vector3 CollisionDetection::closestPointOnLineSegment(
Vector3 CollisionDetection::closestPointOnTrianglePerimeter(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& point) {
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& point) {
Vector3 v[3] = {v0, v1, v2};
Vector3 edgeDirection[3] = {(v1 - v0), (v2 - v1), (v0 - v2)};
@@ -2000,11 +2007,11 @@ Vector3 CollisionDetection::closestPointOnTrianglePerimeter(
bool CollisionDetection::isPointInsideTriangle(
- const Vector3& v0,
- const Vector3& v1,
- const Vector3& v2,
- const Vector3& normal,
- const Vector3& point,
+ const Vector3& v0,
+ const Vector3& v1,
+ const Vector3& v2,
+ const Vector3& normal,
+ const Vector3& point,
float b[3],
Vector3::Axis primaryAxis) {
diff --git a/dep/g3dlite/source/Color1.cpp b/dep/g3dlite/source/Color1.cpp
index 04f3f9412b1..6347a4a05da 100644
--- a/dep/g3dlite/source/Color1.cpp
+++ b/dep/g3dlite/source/Color1.cpp
@@ -1,17 +1,17 @@
/**
- @file Color1.cpp
+ \file Color1.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-30
- @edited 2009-03-27
+ \created 2007-01-30
+ \edited 2011-08-27
*/
#include "G3D/platform.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/Color3.h"
@@ -50,8 +50,8 @@ void Color1::serialize(BinaryOutput& bo) const {
}
-Color1::Color1(const class Color1uint8& other) {
- value = other.value / 255.0f;
+Color1::Color1(const class Color1unorm8& other) {
+ value = other.value;
}
} // namespace G3D
diff --git a/dep/g3dlite/source/Color1uint8.cpp b/dep/g3dlite/source/Color1uint8.cpp
deleted file mode 100644
index 21cd564ba92..00000000000
--- a/dep/g3dlite/source/Color1uint8.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-/**
- @file Color1uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-30
- @edited 2007-01-30
- */
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color1.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color1uint8::Color1uint8(const class Color1& c) : value(iClamp(iFloor(c.value * 256), 0, 255)) {
-}
-
-
-Color1uint8::Color1uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color1uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(value);
-}
-
-
-void Color1uint8::deserialize(class BinaryInput& bi) {
- value = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Color3.cpp b/dep/g3dlite/source/Color3.cpp
index deb0bd87ee7..bc50aaf40ab 100644
--- a/dep/g3dlite/source/Color3.cpp
+++ b/dep/g3dlite/source/Color3.cpp
@@ -1,12 +1,12 @@
/**
- @file Color3.cpp
+ \file Color3.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2010-01-28
+ \created 2001-06-02
+ \edited 2013-03-29
*/
#include "G3D/platform.h"
@@ -16,21 +16,26 @@
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
-#include "G3D/Color3uint8.h"
+#include "G3D/Color3unorm8.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
namespace G3D {
+Color3& Color3::operator=(const Any& a) {
+ *this = Color3(a);
+ return *this;
+}
+
+
Color3::Color3(const Any& any) {
*this = Color3::zero();
- any.verifyName("Color3");
- std::string name = toLower(any.name());
+ any.verifyNameBeginsWith("Color3", "Power3", "Radiance3", "Irradiance3", "Energy3", "Radiosity3", "Biradiance3");
switch (any.type()) {
case Any::TABLE:
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "r") {
r = it->value;
@@ -44,22 +49,38 @@ Color3::Color3(const Any& any) {
}
break;
- case Any::ARRAY:
- if (name == "color3") {
- any.verifySize(3);
- r = any[0];
- g = any[1];
- b = any[2];
- } else if (name == "color3::one") {
- any.verifySize(0);
- *this = one();
- } else if (name == "color3::zero") {
- any.verifySize(0);
- *this = zero();
- } else if (name == "color3::fromargb") {
- *this = Color3::fromARGB((int)any[0].number());
- } else {
- any.verify(false, "Expected Color3 constructor");
+ case Any::ARRAY: // Intentionally falls through
+ case Any::EMPTY_CONTAINER:
+ {
+ const std::string& name = any.name();
+ std::string factoryName;
+ size_t i = name.find("::");
+ if (i != std::string::npos && i > 1) {
+ factoryName = name.substr(i + 2);
+ }
+
+ if (factoryName == "") {
+ if (any.size() == 1) {
+ r = g = b = any[0];
+ } else {
+ any.verifySize(3);
+ r = any[0];
+ g = any[1];
+ b = any[2];
+ }
+ } else if (factoryName == "one") {
+ any.verifySize(0);
+ *this = one();
+ } else if (factoryName == "zero") {
+ any.verifySize(0);
+ *this = zero();
+ } else if (factoryName == "fromARGB") {
+ *this = Color3::fromARGB((int)any[0].number());
+ } else if (factoryName == "fromASRGB") {
+ *this = Color3::fromASRGB((int)any[0].number());
+ } else {
+ any.verify(false, "Expected Color3 constructor");
+ }
}
break;
@@ -69,7 +90,7 @@ Color3::Color3(const Any& any) {
}
-Color3::operator Any() const {
+Any Color3::toAny() const {
Any a(Any::ARRAY, "Color3");
a.append(r, g, b);
return a;
@@ -169,7 +190,7 @@ const Color3& Color3::gray() {
const Color3& Color3::white() {
- static Color3 c(1, 1, 1);
+ static Color3 c(1.0f, 1.0f, 1.0f);
return c;
}
@@ -224,15 +245,16 @@ Color3::Color3(const Vector3& v) {
}
-Color3::Color3(const class Color3uint8& other) {
- r = other.r / 255.0f;
- g = other.g / 255.0f;
- b = other.b / 255.0f;
+Color3::Color3(const class Color3unorm8& other) : r(other.r), g(other.g), b(other.b) {
}
Color3 Color3::fromARGB(uint32 x) {
- return Color3((float)((x >> 16) & 0xFF), (float)((x >> 8) & 0xFF), (float)(x & 0xFF)) / 255.0f;
+ return Color3(Color3unorm8::fromARGB(x));
+}
+
+Color3 Color3::fromASRGB(uint32 x) {
+ return Color3(Color3unorm8::fromARGB(x)).pow(2.2f);
}
//----------------------------------------------------------------------------
@@ -247,7 +269,7 @@ Color3 Color3::random() {
//----------------------------------------------------------------------------
Color3& Color3::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
r *= fInvScalar;
g *= fInvScalar;
b *= fInvScalar;
@@ -262,10 +284,10 @@ Color3& Color3::operator/= (float fScalar) {
//----------------------------------------------------------------------------
float Color3::unitize (float fTolerance) {
- float fLength = length();
+ float fLength = length();
if ( fLength > fTolerance ) {
- float fInvLength = 1.0f / fLength;
+ float fInvLength = 1.0f / fLength;
r *= fInvLength;
g *= fInvLength;
b *= fInvLength;
@@ -313,56 +335,56 @@ Color3 Color3::fromHSV(const Vector3& _hsv) {
Vector3 Color3::toHSV(const Color3& _rgb) {
- debugAssertM((_rgb.r <= 1.0f && _rgb.r >= 0.0f)
- && (_rgb.g <= 1.0f && _rgb.g >= 0.0f)
- && (_rgb.b <= 1.0f && _rgb.b >= 0.0f), "R,G,B must be between [0,1]");
- Vector3 hsv = Vector3::zero();
- hsv.z = G3D::max(G3D::max(_rgb.r, _rgb.g), _rgb.b);
- if (G3D::fuzzyEq(hsv.z, 0.0f)) {
- return hsv;
- }
-
+ debugAssertM((_rgb.r <= 1.0f && _rgb.r >= 0.0f)
+ && (_rgb.g <= 1.0f && _rgb.g >= 0.0f)
+ && (_rgb.b <= 1.0f && _rgb.b >= 0.0f), "R,G,B must be between [0,1]");
+ Vector3 hsv = Vector3::zero();
+ hsv.z = G3D::max(G3D::max(_rgb.r, _rgb.g), _rgb.b);
+ if (G3D::fuzzyEq(hsv.z, 0.0f)) {
+ return hsv;
+ }
+
const float x = G3D::min(G3D::min(_rgb.r, _rgb.g), _rgb.b);
- hsv.y = (hsv.z - x) / hsv.z;
+ hsv.y = (hsv.z - x) / hsv.z;
if (G3D::fuzzyEq(hsv.y, 0.0f)) {
- return hsv;
- }
-
- Vector3 rgbN;
- rgbN.x = (hsv.z - _rgb.r) / (hsv.z - x);
- rgbN.y = (hsv.z - _rgb.g) / (hsv.z - x);
- rgbN.z = (hsv.z - _rgb.b) / (hsv.z - x);
-
- if (_rgb.r == hsv.z) { // note from the max we know that it exactly equals one of the three.
- hsv.x = (_rgb.g == x)? 5.0f + rgbN.z : 1.0f - rgbN.y;
- } else if (_rgb.g == hsv.z) {
- hsv.x = (_rgb.b == x)? 1.0f + rgbN.x : 3.0f - rgbN.z;
- } else {
- hsv.x = (_rgb.r == x)? 3.0f + rgbN.y : 5.0f - rgbN.x;
- }
-
+ return hsv;
+ }
+
+ Vector3 rgbN;
+ rgbN.x = (hsv.z - _rgb.r) / (hsv.z - x);
+ rgbN.y = (hsv.z - _rgb.g) / (hsv.z - x);
+ rgbN.z = (hsv.z - _rgb.b) / (hsv.z - x);
+
+ if (_rgb.r == hsv.z) { // note from the max we know that it exactly equals one of the three.
+ hsv.x = (_rgb.g == x)? 5.0f + rgbN.z : 1.0f - rgbN.y;
+ } else if (_rgb.g == hsv.z) {
+ hsv.x = (_rgb.b == x)? 1.0f + rgbN.x : 3.0f - rgbN.z;
+ } else {
+ hsv.x = (_rgb.r == x)? 3.0f + rgbN.y : 5.0f - rgbN.x;
+ }
+
hsv.x /= 6.0f;
- return hsv;
+ return hsv;
}
Color3 Color3::jetColorMap(const float& val) {
- debugAssertM(val <= 1.0f && val >= 0.0f , "value should be in [0,1]");
+ debugAssertM(val <= 1.0f && val >= 0.0f , "value should be in [0,1]");
- //truncated triangles where sides have slope 4
- Color3 jet;
+ //truncated triangles where sides have slope 4
+ Color3 jet;
- jet.r = G3D::min(4.0f * val - 1.5f,-4.0f * val + 4.5f) ;
- jet.g = G3D::min(4.0f * val - 0.5f,-4.0f * val + 3.5f) ;
- jet.b = G3D::min(4.0f * val + 0.5f,-4.0f * val + 2.5f) ;
+ jet.r = G3D::min(4.0f * val - 1.5f,-4.0f * val + 4.5f) ;
+ jet.g = G3D::min(4.0f * val - 0.5f,-4.0f * val + 3.5f) ;
+ jet.b = G3D::min(4.0f * val + 0.5f,-4.0f * val + 2.5f) ;
- jet.r = G3D::clamp(jet.r, 0.0f, 1.0f);
- jet.g = G3D::clamp(jet.g, 0.0f, 1.0f);
- jet.b = G3D::clamp(jet.b, 0.0f, 1.0f);
+ jet.r = G3D::clamp(jet.r, 0.0f, 1.0f);
+ jet.g = G3D::clamp(jet.g, 0.0f, 1.0f);
+ jet.b = G3D::clamp(jet.b, 0.0f, 1.0f);
- return jet;
+ return jet;
}
diff --git a/dep/g3dlite/source/Color3uint8.cpp b/dep/g3dlite/source/Color3uint8.cpp
deleted file mode 100644
index a744710c752..00000000000
--- a/dep/g3dlite/source/Color3uint8.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-/**
- @file Color3uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-04-07
- @edited 2006-01-07
- */
-
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color3.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color3uint8::Color3uint8(const class Color3& c) {
- r = iMin(255, iFloor(c.r * 256));
- g = iMin(255, iFloor(c.g * 256));
- b = iMin(255, iFloor(c.b * 256));
-}
-
-
-Color3uint8::Color3uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color3uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(r);
- bo.writeUInt8(g);
- bo.writeUInt8(b);
-}
-
-
-void Color3uint8::deserialize(class BinaryInput& bi) {
- r = bi.readUInt8();
- g = bi.readUInt8();
- b = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Color4.cpp b/dep/g3dlite/source/Color4.cpp
index eab09eb9c7e..5c1117c6b0e 100644
--- a/dep/g3dlite/source/Color4.cpp
+++ b/dep/g3dlite/source/Color4.cpp
@@ -1,20 +1,17 @@
/**
- @file Color4.cpp
+ \file Color4.cpp
Color class.
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions by Laura Wollstadt, graphics3d.com
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
+ \author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2002-06-25
- @edited 2009-11-10
+ \created 2002-06-25
+ \edited 2011-09-10
*/
#include <stdlib.h>
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Vector4.h"
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
@@ -24,38 +21,39 @@
namespace G3D {
+
Color4::Color4(const Any& any) {
*this = Color4::zero();
- any.verifyName("Color4");
-
- if (any.type() == Any::TABLE) {
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& key = toLower(it->key);
- if (key == "r") {
- r = it->value;
- } else if (key == "g") {
- g = it->value;
- } else if (key == "b") {
- b = it->value;
- } else if (key == "a") {
- a = it->value;
- } else {
- any.verify(false, "Illegal key: " + it->key);
- }
- }
- } else if (toLower(any.name()) == "color4") {
- r = any[0];
- g = any[1];
- b = any[2];
- a = any[3];
+
+ any.verifyNameBeginsWith("Color", "Power", "Radiance", "Irradiance", "Energy", "Radiosity", "Biradiance");
+
+ if (any.name().find('3') != std::string::npos) {
+ // This is a Color3 constructor--extend with alpha = 1
+ *this = Color4(Color3(any), 1.0f);
} else {
- any.verifyName("Color4::fromARGB");
- *this = Color4::fromARGB((int)any[0].number());
+
+ if (any.type() == Any::TABLE) {
+ any.verifyName("Color4");
+ AnyTableReader atr(any);
+ atr.getIfPresent("r", r);
+ atr.getIfPresent("g", g);
+ atr.getIfPresent("b", b);
+ atr.getIfPresent("a", a);
+ atr.verifyDone();
+ } else if (toLower(any.name()) == "color4") {
+ r = any[0];
+ g = any[1];
+ b = any[2];
+ a = any[3];
+ } else {
+ any.verifyName("Color4::fromARGB");
+ *this = Color4::fromARGB((uint32)any[0].number());
+ }
}
}
-Color4::operator Any() const {
+Any Color4::toAny() const {
Any any(Any::ARRAY, "Color4");
any.append(r, g, b, a);
return any;
@@ -99,8 +97,7 @@ Color4::Color4(const Vector4& v) {
}
-Color4::Color4(const Color4uint8& c) : r(c.r), g(c.g), b(c.b), a(c.a) {
- *this /= 255.0f;
+Color4::Color4(const Color4unorm8& c) : r(c.r), g(c.g), b(c.b), a(c.a) {
}
size_t Color4::hashCode() const {
@@ -148,7 +145,7 @@ Color4 Color4::operator/ (float fScalar) const {
Color4 kQuot;
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
kQuot.r = fInvScalar * r;
kQuot.g = fInvScalar * g;
kQuot.b = fInvScalar * b;
@@ -165,7 +162,7 @@ Color4 Color4::operator/ (float fScalar) const {
Color4& Color4::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
r *= fInvScalar;
g *= fInvScalar;
b *= fInvScalar;
diff --git a/dep/g3dlite/source/Color4uint8.cpp b/dep/g3dlite/source/Color4uint8.cpp
deleted file mode 100644
index 5cc3a578aca..00000000000
--- a/dep/g3dlite/source/Color4uint8.cpp
+++ /dev/null
@@ -1,47 +0,0 @@
-/**
- @file Color4uint8.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-04-07
- @edited 2006-01-07
- */
-#include "G3D/platform.h"
-#include "G3D/g3dmath.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-namespace G3D {
-
-Color4uint8::Color4uint8(const class Color4& c) {
- r = iMin(255, iFloor(c.r * 256));
- g = iMin(255, iFloor(c.g * 256));
- b = iMin(255, iFloor(c.b * 256));
- a = iMin(255, iFloor(c.a * 256));
-}
-
-
-Color4uint8::Color4uint8(class BinaryInput& bi) {
- deserialize(bi);
-}
-
-
-void Color4uint8::serialize(class BinaryOutput& bo) const {
- bo.writeUInt8(r);
- bo.writeUInt8(g);
- bo.writeUInt8(b);
- bo.writeUInt8(a);
-}
-
-
-void Color4uint8::deserialize(class BinaryInput& bi) {
- r = bi.readUInt8();
- g = bi.readUInt8();
- b = bi.readUInt8();
- a = bi.readUInt8();
-}
-
-
-}
diff --git a/dep/g3dlite/source/Cone.cpp b/dep/g3dlite/source/Cone.cpp
index 3104b8424a7..586ccfd6761 100644
--- a/dep/g3dlite/source/Cone.cpp
+++ b/dep/g3dlite/source/Cone.cpp
@@ -17,6 +17,24 @@
namespace G3D {
+
+float Cone::solidAngleFromHalfAngle(float halfAngle){
+ return 2.0f * pif() * (1 - cosf(halfAngle));
+}
+
+double Cone::solidAngleFromHalfAngle(double halfAngle){
+ return 2.0 * pi() * (1.0 - cos(halfAngle));
+}
+
+float Cone::halfAngleFromSolidAngle(float solidAngle){
+ return acos((1.0f - (solidAngle / (2.0f * pif()))));
+}
+
+double Cone::halfAngleFromSolidAngle(double solidAngle){
+ return aCos((1.0 - (solidAngle / (2.0 * pi()))));
+}
+
+
Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) {
this->tip = tip;
this->direction = direction.direction();
@@ -26,6 +44,42 @@ Cone::Cone(const Vector3 &tip, const Vector3 &direction, float angle) {
debugAssert(angle <= pi());
}
+Vector3 Cone::randomDirectionInCone(Random& rng) const {
+ const float cosThresh = cos(angle);
+
+ float cosAngle;
+ float normalizer;
+ Vector3 v;
+ do {
+ float vlenSquared;
+
+ // Sample uniformly on a sphere by rejection sampling and then normalizing
+ do {
+ v.x = rng.uniform(-1, 1);
+ v.y = rng.uniform(-1, 1);
+ v.z = rng.uniform(-1, 1);
+
+ // Sample uniformly on a cube
+ vlenSquared = v.squaredLength();
+ } while (vlenSquared > 1);
+
+
+ const float temp = v.dot(direction);
+
+ // Compute 1 / ||v||, but
+ // if the vector is in the wrong hemisphere, flip the sign
+ normalizer = rsqrt(vlenSquared) * sign(temp);
+
+ // Cosine of the angle between v and the light's negative-z axis
+ cosAngle = temp * normalizer;
+
+ } while (cosAngle < cosThresh);
+
+ // v was within the cone. Normalize it and maybe flip the hemisphere.
+ return v * normalizer;
+ }
+
+
/**
Forms the smallest cone that contains the box. Undefined if
the tip is inside or on the box.
diff --git a/dep/g3dlite/source/ConvexPolyhedron.cpp b/dep/g3dlite/source/ConvexPolyhedron.cpp
index 5fa76e3ed41..b76d9160b34 100644
--- a/dep/g3dlite/source/ConvexPolyhedron.cpp
+++ b/dep/g3dlite/source/ConvexPolyhedron.cpp
@@ -27,7 +27,7 @@ ConvexPolygon::ConvexPolygon(const Vector3& v0, const Vector3& v1, const Vector3
bool ConvexPolygon::isEmpty() const {
- return (_vertex.length() == 0) || (getArea() <= fuzzyEpsilon);
+ return (_vertex.length() == 0) || (getArea() <= fuzzyEpsilon32);
}
@@ -41,7 +41,7 @@ float ConvexPolygon::getArea() const {
int length = _vertex.length();
// Split into triangle fan, compute individual area
- for (int v = 2; v < length; v++) {
+ for (int v = 2; v < length; ++v) {
int i0 = 0;
int i1 = v - 1;
int i2 = v;
@@ -110,7 +110,7 @@ void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon
below._vertex.append(_vertex[v]);
}
- for (v = 1; v < length; v++) {
+ for (v = 1; v < length; ++v) {
bool isAbove = plane.halfSpaceContains(_vertex[v]);
if (lastAbove ^ isAbove) {
@@ -141,7 +141,7 @@ void ConvexPolygon::cut(const Plane& plane, ConvexPolygon &above, ConvexPolygon
} else {
newEdge.start = interp;
}
- count++;
+ ++count;
}
lastAbove = isAbove;
@@ -191,7 +191,7 @@ ConvexPolygon ConvexPolygon::inverse() const {
int length = _vertex.length();
result._vertex.resize(length);
- for (int v = 0; v < length; v++) {
+ for (int v = 0; v < length; ++v) {
result._vertex[v] = _vertex[length - v - 1];
}
@@ -210,7 +210,7 @@ void ConvexPolygon::removeDuplicateVertices(){
--i; // Don't move forward.
}
}
-
+
// Check the last vertex against the first.
if (_vertex[_vertex.size()-1].fuzzyEq(_vertex[0])){
_vertex.pop();
@@ -239,7 +239,7 @@ float ConvexPolyhedron::getVolume() const {
// Choose the first _vertex of the first face as the origin.
// This lets us skip one face, too, and avoids negative heights.
Vector3 v0 = face[0]._vertex[0];
- for (int f = 1; f < face.length(); f++) {
+ for (int f = 1; f < face.length(); ++f) {
const ConvexPolygon& poly = face[f];
float height = (poly._vertex[0] - v0).dot(poly.normal());
@@ -252,7 +252,7 @@ float ConvexPolyhedron::getVolume() const {
}
bool ConvexPolyhedron::isEmpty() const {
- return (face.length() == 0) || (getVolume() <= fuzzyEpsilon);
+ return (face.length() == 0) || (getVolume() <= fuzzyEpsilon32);
}
void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPolyhedron &below) {
@@ -280,11 +280,11 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
for (int v = poly._vertex.length() - 1; (v >= 0) && (!ruledOut); v--) {
double r = abc.dot(poly._vertex[v]) + d;
if (r > eps) {
- numAbove++;
+ ++numAbove;
} else if (r < -eps) {
- numBelow++;
+ ++numBelow;
} else {
- numIn++;
+ ++numIn;
}
ruledOut = (numAbove != 0) && (numBelow !=0);
@@ -333,11 +333,11 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
const Array<Vector3>& _vertex = (aEmpty ? b._vertex : a._vertex);
int L = _vertex.length();
int count = 0;
- for (int v = 0; v < L; v++) {
+ for (int v = 0; v < L; ++v) {
if (plane.fuzzyContains(_vertex[v]) && plane.fuzzyContains(_vertex[(v + 1) % L])) {
e.start = _vertex[v];
e.stop = _vertex[(v + 1) % L];
- count++;
+ ++count;
}
}
@@ -366,7 +366,7 @@ void ConvexPolyhedron::cut(const Plane& plane, ConvexPolyhedron &above, ConvexPo
// Collect the final polgyon by sorting the edges
int numVertices = edge.length();
/*debugPrintf("\n");
-for (int xx=0; xx < numVertices; xx++) {
+for (int xx=0; xx < numVertices; ++xx) {
std::string s1 = edge[xx].start.toString();
std::string s2 = edge[xx].stop.toString();
debugPrintf("%s -> %s\n", s1.c_str(), s2.c_str());
@@ -387,7 +387,7 @@ for (int xx=0; xx < numVertices; xx++) {
int index = 0;
int num = edge.length();
double distance = (edge[index].start - last_vertex).squaredMagnitude();
- for (int e = 1; e < num; e++) {
+ for (int e = 1; e < num; ++e) {
double d = (edge[e].start - last_vertex).squaredMagnitude();
if (d < distance) {
@@ -430,7 +430,7 @@ bool ConvexPolygon2D::contains(const Vector2& p, bool reverse) const {
// the polygon. (To adapt this algorithm for a concave polygon,
// the *sum* of the areas must be non-negative).
- float r = reverse ? -1 : 1;
+ float r = reverse ? -1.0f : 1.0f;
for (int i0 = 0; i0 < m_vertex.size(); ++i0) {
int i1 = (i0 + 1) % m_vertex.size();
diff --git a/dep/g3dlite/source/CoordinateFrame.cpp b/dep/g3dlite/source/CoordinateFrame.cpp
index 7f9a4c098a5..e2c08a54e80 100644
--- a/dep/g3dlite/source/CoordinateFrame.cpp
+++ b/dep/g3dlite/source/CoordinateFrame.cpp
@@ -1,14 +1,14 @@
/**
- @file CoordinateFrame.cpp
+ \file CoordinateFrame.cpp
Coordinate frame class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-06-02
- @edited 2010-03-13
+ \created 2001-06-02
+ \edited 2012-09-29
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -28,16 +28,17 @@
#include "G3D/stringutils.h"
#include "G3D/PhysicsFrame.h"
#include "G3D/UprightFrame.h"
+#include "G3D/Frustum.h"
namespace G3D {
std::string CoordinateFrame::toXYZYPRDegreesString() const {
- UprightFrame uframe(*this);
+ float x,y,z,yaw,pitch,roll;
+ getXYZYPRDegrees(x,y,z,yaw,pitch,roll);
return format("CFrame::fromXYZYPRDegrees(% 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff, % 5.1ff)",
- uframe.translation.x, uframe.translation.y, uframe.translation.z,
- toDegrees(uframe.yaw), toDegrees(uframe.pitch), 0.0f);
+ x,y,z,yaw,pitch,roll);
}
@@ -46,10 +47,12 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
const std::string& n = toUpper(any.name());
- if (beginsWith(n, "VECTOR3")) {
- translation = any;
+ if (beginsWith(n, "VECTOR3") || beginsWith(n, "POINT3")) {
+ translation = Point3(any);
} else if (beginsWith(n, "MATRIX3")) {
- rotation = any;
+ rotation = Matrix3(any);
+ } else if (beginsWith(n, "MATRIX4")) {
+ *this = Matrix4(any).approxCoordinateFrame();
} else if ((n == "CFRAME") || (n == "COORDINATEFRAME")) {
any.verifyType(Any::TABLE, Any::ARRAY);
if (any.type() == Any::ARRAY) {
@@ -57,19 +60,15 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
rotation = any[0];
translation = any[1];
} else {
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& n = toLower(it->key);
- if (n == "translation") {
- translation = Vector3(it->value);
- } else if (n == "rotation") {
- rotation = Matrix3(it->value);
- } else {
- any.verify(false, "Illegal table key: " + it->key);
- }
- }
+ AnyTableReader r(any);
+ r.getIfPresent("translation", translation);
+ r.getIfPresent("rotation", rotation);
+ r.verifyDone();
}
} else if (beginsWith(n, "PHYSICSFRAME") || beginsWith(n, "PFRAME")) {
*this = PhysicsFrame(any);
+// } else if (beginsWith(n, "UPRIGHTFRAME") || beginsWith(n, "UFRAME")) {
+// *this = UprightFrame(any);
} else {
any.verifyName("CFrame::fromXYZYPRDegrees", "CoordinateFrame::fromXYZYPRDegrees");
any.verifyType(Any::ARRAY);
@@ -78,18 +77,18 @@ CoordinateFrame::CoordinateFrame(const Any& any) {
int s = any.size();
*this = fromXYZYPRDegrees(any[0], any[1], any[2],
- (s > 3) ? any[3].number() : 0.0f,
- (s > 4) ? any[4].number() : 0.0f,
- (s > 5) ? any[5].number() : 0.0f);
+ (s > 3) ? (float)any[3].number() : 0.0f,
+ (s > 4) ? (float)any[4].number() : 0.0f,
+ (s > 5) ? (float)any[5].number() : 0.0f);
}
}
-CoordinateFrame::operator Any() const {
+Any CoordinateFrame::toAny() const {
float x, y, z, yaw, pitch, roll;
getXYZYPRDegrees(x, y, z, yaw, pitch, roll);
Any a(Any::ARRAY, "CFrame::fromXYZYPRDegrees");
- a.append(x, y, z, yaw);
+ a.append(x, y, z);
if ( ! G3D::fuzzyEq(yaw, 0.0f) || ! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
a.append(yaw);
if (! G3D::fuzzyEq(pitch, 0.0f) || ! G3D::fuzzyEq(roll, 0.0f)) {
@@ -114,11 +113,7 @@ CoordinateFrame::CoordinateFrame() :
CoordinateFrame CoordinateFrame::fromXYZYPRRadians(float x, float y, float z, float yaw,
float pitch, float roll) {
- Matrix3 rotation = Matrix3::fromAxisAngle(Vector3::unitY(), yaw);
-
- rotation = Matrix3::fromAxisAngle(rotation.column(0), pitch) * rotation;
- rotation = Matrix3::fromAxisAngle(rotation.column(2), roll) * rotation;
-
+ const Matrix3& rotation = Matrix3::fromEulerAnglesYXZ(yaw, pitch, roll);
const Vector3 translation(x, y, z);
return CoordinateFrame(rotation, translation);
@@ -131,28 +126,7 @@ void CoordinateFrame::getXYZYPRRadians(float& x, float& y, float& z,
y = translation.y;
z = translation.z;
- const Vector3& look = lookVector();
-
- if (abs(look.y) > 0.99f) {
- // Looking nearly straight up or down
-
- yaw = G3D::pi() + atan2(look.x, look.z);
- pitch = asin(look.y);
- roll = 0.0f;
-
- } else {
-
- // Yaw cannot be affected by others, so pull it first
- yaw = G3D::pi() + atan2(look.x, look.z);
-
- // Pitch is the elevation of the yaw vector
- pitch = asin(look.y);
-
- Vector3 actualRight = rightVector();
- Vector3 expectedRight = look.cross(Vector3::unitY());
-
- roll = 0;//acos(actualRight.dot(expectedRight)); TODO
- }
+ rotation.toEulerAnglesYXZ(yaw, pitch, roll);
}
@@ -234,24 +208,55 @@ std::string CoordinateFrame::toXML() const {
Plane CoordinateFrame::toObjectSpace(const Plane& p) const {
+ // TODO
Vector3 N, P;
double d;
p.getEquation(N, d);
P = N * (float)d;
P = pointToObjectSpace(P);
N = normalToObjectSpace(N);
+ debugAssertM(isFinite(d), "Not implemented for infinite planes");
return Plane(N, P);
}
-Plane CoordinateFrame::toWorldSpace(const Plane& p) const {
- Vector3 N, P;
- double d;
- p.getEquation(N, d);
- P = N * (float)d;
- P = pointToWorldSpace(P);
- N = normalToWorldSpace(N);
- return Plane(N, P);
+Frustum CoordinateFrame::toWorldSpace(const Frustum& f) const {
+ Frustum g;
+ g.vertexPos.resize(f.vertexPos.size());
+ g.faceArray.resize(f.faceArray.size());
+
+ for (int i = 0; i < f.vertexPos.size(); ++i) {
+ g.vertexPos[i] = toWorldSpace(f.vertexPos[i]);
+ }
+ for (int i = 0; i < f.faceArray.size(); ++i) {
+ g.faceArray[i].plane = toWorldSpace(f.faceArray[i].plane);
+ for (int j = 0; j < 4; ++j) {
+ g.faceArray[i].vertexIndex[j] = f.faceArray[i].vertexIndex[j];
+ }
+ }
+
+ return g;
+}
+
+
+Plane CoordinateFrame::toWorldSpace(const Plane& plane) const {
+ // Since there is no scale factor, we don't have to
+ // worry about the inverse transpose of the normal.
+ Vector3 normal;
+ float d;
+
+ plane.getEquation(normal, d);
+
+ const Vector3& newNormal = rotation * normal;
+
+ if (isFinite(d)) {
+ d = (newNormal * -d + translation).dot(newNormal);
+ return Plane(newNormal, newNormal * d);
+ } else {
+ // When d is infinite, we can't multiply 0's by it without
+ // generating NaNs.
+ return Plane::fromEquation(newNormal.x, newNormal.y, newNormal.z, d);
+ }
}
@@ -285,6 +290,20 @@ Capsule CoordinateFrame::toWorldSpace(const Capsule& c) const {
}
+void CoordinateFrame::toWorldSpace(const AABox& b, AABox& result) const {
+ if (b.isEmpty()) {
+ result = b;
+ } else if (! b.isFinite()) {
+ // We can't combine infinite elements under a matrix
+ // multiplication: if the computation performs inf-inf we'll
+ // get NaN. So treat the box as infinite in all directions.
+ result = AABox::inf();
+ } else {
+ toWorldSpace(Box(b)).getBounds(result);
+ }
+}
+
+
Box CoordinateFrame::toWorldSpace(const AABox& b) const {
Box b2(b);
return toWorldSpace(b2);
@@ -292,18 +311,17 @@ Box CoordinateFrame::toWorldSpace(const AABox& b) const {
Box CoordinateFrame::toWorldSpace(const Box& b) const {
- Box out(b);
-
- for (int i = 0; i < 8; ++i) {
- out._corner[i] = pointToWorldSpace(b._corner[i]);
- debugAssert(! isNaN(out._corner[i].x));
+ if(!b.isFinite()) {
+ return b;
}
-
+ Box out(b);
+ out._center = pointToWorldSpace(b._center);
for (int i = 0; i < 3; ++i) {
- out._axis[i] = vectorToWorldSpace(b._axis[i]);
+ out._edgeVector[i] = vectorToWorldSpace(out._edgeVector[i]);
}
- out._center = pointToWorldSpace(b._center);
+ out._area = b._area;
+ out._volume = b._volume;
return out;
}
@@ -376,11 +394,11 @@ void CoordinateFrame::lookAt(
}
up -= look * look.dot(up);
- up.unitize();
+ up = up.direction();
Vector3 z = -look;
Vector3 x = -z.cross(up);
- x.unitize();
+ x = x.direction();
Vector3 y = z.cross(x);
@@ -390,6 +408,14 @@ void CoordinateFrame::lookAt(
}
+void CoordinateFrame::moveTowards(const CoordinateFrame& goal, float maxTranslation, float maxRotation) {
+ translation.moveTowards(goal.translation, maxTranslation);
+ Quat q(rotation);
+ q.moveTowards(Quat(goal.rotation), maxRotation);
+ rotation = Matrix3(q);
+}
+
+
CoordinateFrame CoordinateFrame::lerp(
const CoordinateFrame& other,
float alpha) const {
diff --git a/dep/g3dlite/source/Crypto.cpp b/dep/g3dlite/source/Crypto.cpp
index c69b23375ce..8d54fbeeac7 100644
--- a/dep/g3dlite/source/Crypto.cpp
+++ b/dep/g3dlite/source/Crypto.cpp
@@ -11,7 +11,7 @@
#include "G3D/platform.h"
#include "G3D/Crypto.h"
#include "G3D/g3dmath.h"
-#include <zlib.h>
+#include "zlib.h"
namespace G3D {
@@ -64,7 +64,8 @@ int Crypto::numSmallPrimes() {
}
uint32 Crypto::crc32(const void* byte, size_t numBytes) {
- return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), numBytes);
+ alwaysAssertM(numBytes < 0xFFFFFFFF, "Not implemented for arrays larger than 2^32 bytes");
+ return ::crc32(::crc32(0, Z_NULL, 0), static_cast<const Bytef *>(byte), (int)numBytes);
}
} // G3D
diff --git a/dep/g3dlite/source/Crypto_md5.cpp b/dep/g3dlite/source/Crypto_md5.cpp
index c7ee535d61e..6fca6383f93 100644
--- a/dep/g3dlite/source/Crypto_md5.cpp
+++ b/dep/g3dlite/source/Crypto_md5.cpp
@@ -38,9 +38,9 @@ typedef unsigned int md5_word_t; /* 32-bit word */
/* Define the state of the MD5 Algorithm. */
typedef struct md5_state_s {
- md5_word_t count[2]; /* message length in bits, lsw first */
- md5_word_t abcd[4]; /* digest buffer */
- md5_byte_t buf[64]; /* accumulate block */
+ md5_word_t count[2]; /* message length in bits, lsw first */
+ md5_word_t abcd[4]; /* digest buffer */
+ md5_byte_t buf[64]; /* accumulate block */
} md5_state_t;
#ifdef __cplusplus
@@ -55,7 +55,7 @@ static void md5_init(md5_state_t *pms);
static void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+static void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
#ifdef __cplusplus
}
#endif
@@ -100,7 +100,7 @@ MD5Hash Crypto::md5(const void* data, size_t n) {
This code implements the MD5 Algorithm defined in RFC 1321, whose
text is available at
- http://www.ietf.org/rfc/rfc1321.txt
+ http://www.ietf.org/rfc/rfc1321.txt
The code is derived from the text of the RFC, including the test suite
(section A.5) but excluding the rest of Appendix A. It does not include
any code or documentation that is identified in the RFC as being
@@ -111,14 +111,14 @@ MD5Hash Crypto::md5(const void* data, size_t n) {
that follows (in reverse chronological order):
2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
- either statically or dynamically; added missing #include <string.h>
- in library.
+ either statically or dynamically; added missing #include <string.h>
+ in library.
2002-03-11 lpd Corrected argument list for main(), and added int return
- type, in test program and T value program.
+ type, in test program and T value program.
2002-02-21 lpd Added missing #include <stdio.h> in test program.
2000-07-03 lpd Patched to eliminate warnings about "constant is
- unsigned in ANSI C, signed in traditional"; made test program
- self-checking.
+ unsigned in ANSI C, signed in traditional"; made test program
+ self-checking.
1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
1999-05-03 lpd Original version.
@@ -220,8 +220,8 @@ static void
md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
md5_word_t
- a = pms->abcd[0], b = pms->abcd[1],
- c = pms->abcd[2], d = pms->abcd[3];
+ a = pms->abcd[0], b = pms->abcd[1],
+ c = pms->abcd[2], d = pms->abcd[3];
md5_word_t t;
#if BYTE_ORDER > 0
/* Define storage only for big-endian CPUs. */
@@ -234,51 +234,51 @@ md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
{
#if BYTE_ORDER == 0
- /*
- * Determine dynamically whether this is a big-endian or
- * little-endian machine, since we can use a more efficient
- * algorithm on the latter.
- */
- static const int w = 1;
-
- if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+ /*
+ * Determine dynamically whether this is a big-endian or
+ * little-endian machine, since we can use a more efficient
+ * algorithm on the latter.
+ */
+ static const int w = 1;
+
+ if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
#endif
-#if BYTE_ORDER <= 0 /* little-endian */
- {
- /*
- * On little-endian machines, we can process properly aligned
- * data without copying it.
- */
- if (!((data - (const md5_byte_t *)0) & 3)) {
- /* data are properly aligned */
- X = (const md5_word_t *)data;
- } else {
- /* not aligned */
- memcpy(xbuf, data, 64);
- X = xbuf;
- }
- }
+#if BYTE_ORDER <= 0 /* little-endian */
+ {
+ /*
+ * On little-endian machines, we can process properly aligned
+ * data without copying it.
+ */
+ if (!((data - (const md5_byte_t *)0) & 3)) {
+ /* data are properly aligned */
+ X = (const md5_word_t *)data;
+ } else {
+ /* not aligned */
+ memcpy(xbuf, data, 64);
+ X = xbuf;
+ }
+ }
#endif
#if BYTE_ORDER == 0
- else /* dynamic big-endian */
+ else /* dynamic big-endian */
#endif
-#if BYTE_ORDER >= 0 /* big-endian */
- {
- /*
- * On big-endian machines, we must arrange the bytes in the
- * right order.
- */
- const md5_byte_t *xp = data;
- int i;
+#if BYTE_ORDER >= 0 /* big-endian */
+ {
+ /*
+ * On big-endian machines, we must arrange the bytes in the
+ * right order.
+ */
+ const md5_byte_t *xp = data;
+ int i;
# if BYTE_ORDER == 0
- X = xbuf; /* (dynamic only) */
+ X = xbuf; /* (dynamic only) */
# else
-# define xbuf X /* (static only) */
+# define xbuf X /* (static only) */
# endif
- for (i = 0; i < 16; ++i, xp += 4)
- xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
- }
+ for (i = 0; i < 16; ++i, xp += 4)
+ xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+ }
#endif
}
@@ -416,56 +416,56 @@ md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
md5_word_t nbits = (md5_word_t)(nbytes << 3);
if (nbytes <= 0)
- return;
+ return;
/* Update the message length. */
pms->count[1] += nbytes >> 29;
pms->count[0] += nbits;
if (pms->count[0] < nbits)
- pms->count[1]++;
+ pms->count[1]++;
/* Process an initial partial block. */
if (offset) {
- int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
- memcpy(pms->buf + offset, p, copy);
- if (offset + copy < 64)
- return;
- p += copy;
- left -= copy;
- md5_process(pms, pms->buf);
+ int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+ memcpy(pms->buf + offset, p, copy);
+ if (offset + copy < 64)
+ return;
+ p += copy;
+ left -= copy;
+ md5_process(pms, pms->buf);
}
/* Process full blocks. */
for (; left >= 64; p += 64, left -= 64)
- md5_process(pms, p);
+ md5_process(pms, p);
/* Process a final partial block. */
if (left)
- memcpy(pms->buf, p, left);
+ memcpy(pms->buf, p, left);
}
void
md5_finish(md5_state_t *pms, md5_byte_t digest[16])
{
static const md5_byte_t pad[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
md5_byte_t data[8];
int i;
/* Save the length before padding. */
for (i = 0; i < 8; ++i)
- data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+ data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
/* Pad to 56 bytes mod 64. */
md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
/* Append the length. */
md5_append(pms, data, 8);
for (i = 0; i < 16; ++i)
- digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+ digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
}
}
diff --git a/dep/g3dlite/source/Cylinder.cpp b/dep/g3dlite/source/Cylinder.cpp
index 7a7b9f9440d..32d14e96bb8 100644
--- a/dep/g3dlite/source/Cylinder.cpp
+++ b/dep/g3dlite/source/Cylinder.cpp
@@ -22,7 +22,7 @@
namespace G3D {
Cylinder::Cylinder(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
@@ -31,48 +31,48 @@ Cylinder::Cylinder() {
Cylinder::Cylinder(const Vector3& _p1, const Vector3& _p2, float _r)
- : p1(_p1), p2(_p2), mRadius(_r) {
+ : p1(_p1), p2(_p2), mRadius(_r) {
}
void Cylinder::serialize(class BinaryOutput& b) const {
- p1.serialize(b);
- p2.serialize(b);
- b.writeFloat64(mRadius);
+ p1.serialize(b);
+ p2.serialize(b);
+ b.writeFloat64(mRadius);
}
void Cylinder::deserialize(class BinaryInput& b) {
- p1.deserialize(b);
- p2.deserialize(b);
- mRadius = b.readFloat64();
+ p1.deserialize(b);
+ p2.deserialize(b);
+ mRadius = (float)b.readFloat64();
}
Line Cylinder::axis() const {
- return Line::fromTwoPoints(p1, p2);
+ return Line::fromTwoPoints(p1, p2);
}
float Cylinder::radius() const {
- return mRadius;
+ return mRadius;
}
float Cylinder::volume() const {
- return
- (float)pi() * square(mRadius) * (p1 - p2).magnitude();
+ return
+ (float)pi() * square(mRadius) * (p1 - p2).magnitude();
}
float Cylinder::area() const {
- return
+ return
// Sides
- (twoPi() * mRadius) * height() +
+ ((float)twoPi() * mRadius) * height() +
// Caps
- twoPi() * square(mRadius);
+ (float)twoPi() * square(mRadius);
}
void Cylinder::getBounds(AABox& out) const {
diff --git a/dep/g3dlite/source/FileSystem.cpp b/dep/g3dlite/source/FileSystem.cpp
index f082937a908..32a84e77048 100644
--- a/dep/g3dlite/source/FileSystem.cpp
+++ b/dep/g3dlite/source/FileSystem.cpp
@@ -1,10 +1,10 @@
/**
- @file FileSystem.cpp
+ \file FileSystem.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @author 2002-06-06
- @edited 2010-04-10
+ \author 2002-06-06
+ \edited 2010-10-10
*/
#include "G3D/FileSystem.h"
#include "G3D/System.h"
@@ -19,7 +19,7 @@
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
// Needed for _getcwd
# include <direct.h>
@@ -36,16 +36,16 @@
# include <unistd.h>
# define _getcwd getcwd
# define _stat stat
-#endif
-
-#ifdef __CYGWIN__
-#define stat64 stat
+# define stricmp strcasecmp
+# define strnicmp strncasecmp
#endif
namespace G3D {
static FileSystem* common = NULL;
+GMutex FileSystem::mutex;
+
FileSystem& FileSystem::instance() {
init();
return *common;
@@ -70,24 +70,24 @@ FileSystem::FileSystem() : m_cacheLifetime(10) {}
/////////////////////////////////////////////////////////////
-bool FileSystem::Dir::contains(const std::string& f) const {
+bool FileSystem::Dir::contains(const std::string& f, bool caseSensitive) const {
for (int i = 0; i < nodeArray.size(); ++i) {
-# ifdef G3D_WIN32
- if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
- return true;
- }
-# else
+ if (caseSensitive) {
if (f == nodeArray[i].name) {
return true;
}
-# endif
+ } else if (stricmp(f.c_str(), nodeArray[i].name.c_str()) == 0) {
+ return true;
+ }
}
return false;
}
+
-void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& pathInsideZipfile) {
+void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::string& _pathInsideZipfile) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
+ const std::string& pathInsideZipfile = FilePath::canonicalize(_pathInsideZipfile);
struct zip* z = zip_open( FilePath::removeTrailingSlash(zipfile).c_str(), ZIP_CHECKCONS, NULL );
debugAssert(z);
@@ -99,22 +99,23 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
zip_stat_index( z, i, ZIP_FL_NOCASE, &info );
// Fully-qualified name of a file inside zipfile
- std::string name = info.name;
+ std::string name = FilePath::canonicalize(info.name);
if (beginsWith(name, pathInsideZipfile)) {
// We found something inside the directory we were looking for,
- // so the directory itself must exist
+ // so the directory itself must exist
exists = true;
// For building the cached directory listing, extract only elements that do not contain
// additional subdirectories.
- int start = pathInsideZipfile.size();
- if ((int(name.length()) > start) && isSlash(name[start])) {
+ size_t start = pathInsideZipfile.size();
+ if ((name.length() > start) && isSlash(name[start])) {
++start;
}
- int end = findSlash(name, start);
- if (end == -1) {
+
+ size_t end = findSlash(name, start);
+ if (end == std::string::npos) {
// There are no more slashes; add this name
name = name.substr(start);
if (alreadyAdded.insert(name)) {
@@ -126,8 +127,8 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
// There are more slashes, indicating that this is a directory
name = name.substr(start, end);
if (alreadyAdded.insert(name)) {
- Entry& e = nodeArray.next();
- e.name = name;
+ Entry& e = nodeArray.next();
+ e.name = FilePath::removeTrailingSlash(name);
e.type = DIR_TYPE;
}
}
@@ -142,7 +143,7 @@ void FileSystem::Dir::computeZipListing(const std::string& zipfile, const std::s
FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpdate) {
const std::string& key =
-# if defined(G3D_WIN32)
+# if defined(G3D_WINDOWS)
FilePath::canonicalize(FilePath::removeTrailingSlash(toLower(FilePath::canonicalize(resolve(path)))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(FilePath::canonicalize(resolve(path))));
@@ -156,10 +157,17 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
// Out of date: update
dir.lastChecked = now;
-
- struct _stat st;
- const bool exists = _stat(key.c_str(), &st) != -1;
- const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
+# ifdef G3D_WINDOWS
+ // On windows, we have to use GetFileAttributes (http://msdn.microsoft.com/en-us/library/aa364944(v=vs.85).aspx) instead of
+ // stat in order to work with network shares
+ const DWORD st = GetFileAttributesA(key.c_str());
+ const bool exists = (st != INVALID_FILE_ATTRIBUTES);
+ const bool isDirectory = (st & FILE_ATTRIBUTE_DIRECTORY) != 0;
+# else
+ struct _stat st;
+ const bool exists = _stat(key.c_str(), &st) != -1;
+ const bool isDirectory = (st.st_mode & S_IFDIR) != 0;
+# endif
// Does this path exist on the real filesystem?
if (exists && isDirectory) {
@@ -168,7 +176,7 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
if (isDirectory) {
dir.exists = true;
// Update contents
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const std::string& filespec = FilePath::concat(key, "*");
struct _finddata_t fileinfo;
intptr_t handle = _findfirst(filespec.c_str(), &fileinfo);
@@ -238,7 +246,6 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
// There is a zipfile somewhere in the path. Does
// the rest of the path exist inside the zipfile?
dir.inZipfile = true;
-
dir.computeZipListing(zip, path.substr(zip.length() + 1));
}
}
@@ -248,27 +255,24 @@ FileSystem::Dir& FileSystem::getContents(const std::string& path, bool forceUpda
}
-bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
+bool FileSystem::_inZipfile(const std::string& _path, std::string& z) {
+ const std::string& path = FilePath::expandEnvironmentVariables(_path);
+
// Reject trivial cases before parsing
- if (path.find('.') == std::string::npos) {
- // There is no zipfile possible, since G3D requires
- // an extension on zipfiles.
- return false;
- }
// Look at all sub-paths containing periods.
// For each, ask if it is a zipfile.
- int current = 0;
+ size_t current = 0;
current = path.find('.', current);
- while (current != -1) {
+ while (current != std::string::npos) {
// xxxxx/foo.zip/yyyyy
current = path.find('.', current);
// Look forward for the next slash
- int s = findSlash(path, current);
+ size_t s = findSlash(path, current);
- if (s == -1) {
+ if (s == std::string::npos) {
// No more slashes
return false;
}
@@ -286,17 +290,17 @@ bool FileSystem::_inZipfile(const std::string& path, std::string& z) {
}
-bool FileSystem::_isZipfile(const std::string& filename) {
- if (FilePath::ext(filename).empty()) {
- return false;
- }
+bool FileSystem::_isZipfile(const std::string& _filename) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
+
FILE* f = fopen(FilePath::removeTrailingSlash(filename).c_str(), "r");
if (f == NULL) {
return false;
}
uint8 header[4];
- fread(header, 4, 1, f);
+ (void)fread(header, 4, 1, f);
const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
for (int i = 0; i < 4; ++i) {
@@ -311,7 +315,9 @@ bool FileSystem::_isZipfile(const std::string& filename) {
}
-FILE* FileSystem::_fopen(const char* filename, const char* mode) {
+FILE* FileSystem::_fopen(const char* _filename, const char* mode) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
for (const char* m = mode; *m != '\0'; ++m) {
if (*m == 'w') {
// Purge the cache entry for the parent of this directory
@@ -319,11 +325,15 @@ FILE* FileSystem::_fopen(const char* filename, const char* mode) {
break;
}
}
- return ::fopen(filename, mode);
+
+ markFileUsed(filename);
+ return ::fopen(filename.c_str(), mode);
}
-void FileSystem::_clearCache(const std::string& path) {
+void FileSystem::_clearCache(const std::string& _path) {
+ const std::string& path = FilePath::expandEnvironmentVariables(_path);
+
if ((path == "") || FilePath::isRoot(path)) {
m_cache.clear();
} else {
@@ -331,7 +341,7 @@ void FileSystem::_clearCache(const std::string& path) {
m_cache.getKeys(keys);
const std::string& prefix =
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
toLower(FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path))));
# else
FilePath::canonicalize(FilePath::removeTrailingSlash(_resolve(path)));
@@ -353,8 +363,9 @@ void FileSystem::_setCacheLifetime(float t) {
}
-void FileSystem::_createDirectory(const std::string& dir) {
-
+void FileSystem::_createDirectory(const std::string& _dir) {
+ const std::string& dir = FilePath::expandEnvironmentVariables(_dir);
+
if (dir == "") {
return;
}
@@ -395,7 +406,7 @@ void FileSystem::_createDirectory(const std::string& dir) {
if (! _exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
-# ifndef G3D_WIN32
+# ifndef G3D_WINDOWS
mkdir(p.c_str(), 0777);
# else
_mkdir(p.c_str());
@@ -407,8 +418,10 @@ void FileSystem::_createDirectory(const std::string& dir) {
}
-void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
-# ifdef G3D_WIN32
+void FileSystem::_copyFile(const std::string& _source, const std::string& _dest) {
+ const std::string& source = FilePath::expandEnvironmentVariables(_source);
+ const std::string& dest = FilePath::expandEnvironmentVariables(_dest);
+# ifdef G3D_WINDOWS
// TODO: handle case where srcPath is in a zipfile
CopyFileA(source.c_str(), dest.c_str(), FALSE);
_clearCache(FilePath::parent(_resolve(dest)));
@@ -422,10 +435,11 @@ void FileSystem::_copyFile(const std::string& source, const std::string& dest) {
}
-bool FileSystem::_exists(const std::string& f, bool trustCache) {
+bool FileSystem::_exists(const std::string& _f, bool trustCache, bool caseSensitive) {
+ const std::string& f = FilePath::expandEnvironmentVariables(_f);
if (FilePath::isRoot(f)) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const std::string& winname = toLower(f.substr(0, 1)) + ":\\";
return _drives().contains(winname);
# else
@@ -433,10 +447,11 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
# endif
}
- std::string path = FilePath::removeTrailingSlash(f);
- std::string parentPath = FilePath::parent(path);
+ const std::string& path = FilePath::removeTrailingSlash(f);
+ const std::string& parentPath = FilePath::parent(path);
- const Dir& entry = getContents(parentPath, ! trustCache);
+ const bool forceUpdate = ! trustCache;
+ const Dir& entry = getContents(parentPath, forceUpdate);
if (FilePath::containsWildcards(f)) {
if (! entry.exists) {
@@ -446,15 +461,9 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
const std::string& pattern = FilePath::baseExt(path);
-# ifdef G3D_WIN32
- static const int flags = FNM_CASEFOLD;
-# else
- static const int flags = 0;
-# endif
-
// See if any element of entry matches the wild card
for (int i = 0; i < entry.nodeArray.size(); ++i) {
- if (FilePath::matches(entry.nodeArray[i].name, pattern, flags)) {
+ if (FilePath::matches(entry.nodeArray[i].name, pattern, caseSensitive)) {
return true;
}
}
@@ -463,12 +472,13 @@ bool FileSystem::_exists(const std::string& f, bool trustCache) {
return false;
} else {
- return entry.exists && entry.contains(FilePath::baseExt(path));
+ return entry.exists && entry.contains(FilePath::baseExt(path), caseSensitive);
}
}
-bool FileSystem::_isDirectory(const std::string& filename) {
+bool FileSystem::_isDirectory(const std::string& _filename) {
+ const std::string& filename = FilePath::expandEnvironmentVariables(_filename);
// TODO: work with zipfiles and cache
struct _stat st;
const bool exists = _stat(FilePath::removeTrailingSlash(filename).c_str(), &st) != -1;
@@ -476,14 +486,33 @@ bool FileSystem::_isDirectory(const std::string& filename) {
}
-std::string FileSystem::_resolve(const std::string& filename, const std::string& cwd) {
+void FileSystem::_removeFile(const std::string& path) {
+ alwaysAssertM(! inZipfile(path), "Cannot invoke removeFile() on files inside zipfiles.");
+ Array<std::string> files;
+ getFiles(path, files, true);
+
+ for (int i = 0; i < files.size(); ++i) {
+ const std::string& filename = files[i];
+ int retval = ::remove(filename.c_str());
+ (void)retval;
+ }
+
+ // Remove from cache
+ _clearCache(FilePath::parent(path));
+}
+
+
+std::string FileSystem::_resolve(const std::string& _filename, const std::string& _cwd) {
+ const std::string& filename = FilePath::expandEnvironmentVariables(_filename);
+ const std::string& cwd = FilePath::expandEnvironmentVariables(_cwd);
+
if (filename.size() >= 1) {
if (isSlash(filename[0])) {
// Already resolved
return filename;
} else {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if ((filename.size() >= 2) && (filename[1] == ':')) {
// There is a drive spec on the front.
if ((filename.size() >= 3) && isSlash(filename[2])) {
@@ -511,12 +540,29 @@ std::string FileSystem::_currentDirectory() {
static const int N = 2048;
char buffer[N];
- _getcwd(buffer, N);
+ (void)_getcwd(buffer, N);
return std::string(buffer);
}
-bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
+static Set<std::string> _filesUsed;
+
+void FileSystem::markFileUsed(const std::string& filename) {
+ mutex.lock();
+ _filesUsed.insert(filename);
+ mutex.unlock();
+}
+
+
+const Set<std::string>& FileSystem::usedFiles() {
+ return _filesUsed;
+}
+
+
+bool FileSystem::_isNewer(const std::string& _src, const std::string& _dst) {
+ const std::string& src = FilePath::expandEnvironmentVariables(_src);
+ const std::string& dst = FilePath::expandEnvironmentVariables(_dst);
+
// TODO: work with cache and zipfiles
struct _stat sts;
bool sexists = _stat(src.c_str(), &sts) != -1;
@@ -528,7 +574,9 @@ bool FileSystem::_isNewer(const std::string& src, const std::string& dst) {
}
-int64 FileSystem::_size(const std::string& filename) {
+int64 FileSystem::_size(const std::string& _filename) {
+ const std::string& filename = FilePath::canonicalize(FilePath::expandEnvironmentVariables(_filename));
+
struct stat64 st;
int result = stat64(filename.c_str(), &st);
@@ -544,6 +592,7 @@ int64 FileSystem::_size(const std::string& filename) {
struct zip_stat info;
zip_stat_init( &info ); // Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
+ (void) success;
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
}
@@ -553,7 +602,7 @@ int64 FileSystem::_size(const std::string& filename) {
#endif
return -1;
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- }
+ }
#endif
}
@@ -561,7 +610,12 @@ int64 FileSystem::_size(const std::string& filename) {
}
-void FileSystem::listHelper(const std::string& shortSpec, const std::string& parentPath, Array<std::string>& result, const ListSettings& settings) {
+void FileSystem::listHelper
+(const std::string& shortSpec,
+ const std::string& parentPath,
+ Array<std::string>& result,
+ const ListSettings& settings) {
+
Dir& dir = getContents(parentPath, false);
if (! dir.exists) {
@@ -573,8 +627,10 @@ void FileSystem::listHelper(const std::string& shortSpec, const std::string& par
// See if it matches the spec
if (FilePath::matches(entry.name, shortSpec, settings.caseSensitive)) {
- if ((entry.type == UNKNOWN) && ! (settings.files && settings.directories)) {
- // Update the type
+ if ((entry.type == UNKNOWN) &&
+ (! (settings.files && settings.directories) ||
+ settings.recursive)) {
+ // Update the type: it is unknown and we'll need to branch onit below
entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
}
@@ -589,15 +645,23 @@ void FileSystem::listHelper(const std::string& shortSpec, const std::string& par
}
}
} // match
+
+ if (settings.recursive) {
+ if (entry.type == UNKNOWN) {
+ entry.type = isDirectory(FilePath::concat(parentPath, entry.name)) ? DIR_TYPE : FILE_TYPE;
+ }
- if (settings.recursive && (entry.type == DIR_TYPE)) {
- listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
+ if (entry.type == DIR_TYPE) {
+ listHelper(shortSpec, FilePath::concat(parentPath, entry.name), result, settings);
+ }
}
} // for
}
-void FileSystem::_list(const std::string& spec, Array<std::string>& result, const ListSettings& settings) {
+void FileSystem::_list(const std::string& _spec, Array<std::string>& result, const ListSettings& settings) {
+ const std::string& spec = FilePath::expandEnvironmentVariables(_spec);
+
const std::string& shortSpec = FilePath::baseExt(spec);
const std::string& parentPath = FilePath::parent(spec);
@@ -606,7 +670,7 @@ void FileSystem::_list(const std::string& spec, Array<std::string>& result, cons
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
const Array<std::string>& FileSystem::_drives() {
if (m_winDrive.length() == 0) {
// See http://msdn.microsoft.com/en-us/library/aa364975(VS.85).aspx
@@ -615,10 +679,10 @@ const Array<std::string>& FileSystem::_drives() {
GetLogicalDriveStringsA(bufSize, bufData);
// Drive list is a series of NULL-terminated strings, itself terminated with a NULL.
- for (int i = 0; bufData[i] != '\0'; ++i) {
+ for (size_t i = 0; bufData[i] != '\0'; ++i) {
const char* thisString = bufData + i;
m_winDrive.append(toLower(thisString));
- i += strlen(thisString) + 1;
+ i += strlen(thisString);
}
}
@@ -629,7 +693,7 @@ const Array<std::string>& FileSystem::_drives() {
/////////////////////////////////////////////////////////////////////
bool FilePath::isRoot(const std::string& f) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
if (f.length() < 2) {
return false;
}
@@ -644,9 +708,17 @@ bool FilePath::isRoot(const std::string& f) {
}
}
- if (isSlash(f[0]) && isSlash(f[1])) {
- // e.g., "\\foo\"
- return true;
+ // Windows shares are considered roots, but only if this does not include a path inside the share
+ if (isSlash(f[0]) && isSlash(f[1])) {
+ size_t i = f.find("/", 3);
+ size_t j = f.find("\\", 3);
+
+ if (i == std::string::npos) {
+ i = j;
+ }
+
+ // e.g., "\\foo\", "\\foo"
+ return ((i == std::string::npos) || (i == f.length() - 1));
}
# else
if (f == "/") {
@@ -678,8 +750,8 @@ std::string FilePath::concat(const std::string& dirname, const std::string& file
std::string FilePath::ext(const std::string& filename) {
- int i = filename.rfind(".");
- if (i >= 0) {
+ size_t i = filename.rfind(".");
+ if (i != std::string::npos) {
return filename.substr(i + 1, filename.length() - i);
} else {
return "";
@@ -688,16 +760,16 @@ std::string FilePath::ext(const std::string& filename) {
std::string FilePath::baseExt(const std::string& filename) {
- int i = findLastSlash(filename);
+ size_t i = findLastSlash(filename);
-# ifdef G3D_WIN32
- int j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+# ifdef G3D_WINDOWS
+ size_t j = filename.rfind(":");
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return filename;
} else {
return filename.substr(i + 1, filename.length() - i);
@@ -707,8 +779,8 @@ std::string FilePath::baseExt(const std::string& filename) {
std::string FilePath::base(const std::string& path) {
std::string filename = baseExt(path);
- int i = filename.rfind(".");
- if (i == -1) {
+ size_t i = filename.rfind(".");
+ if (i == std::string::npos) {
// No extension
return filename;
} else {
@@ -718,16 +790,16 @@ std::string FilePath::base(const std::string& path) {
std::string FilePath::parent(const std::string& path) {
- int i = findLastSlash(removeTrailingSlash(path));
+ size_t i = findLastSlash(removeTrailingSlash(path));
-# ifdef G3D_WIN32
- int j = path.rfind(":");
- if ((i == -1) && (j >= 0)) {
+# ifdef G3D_WINDOWS
+ size_t j = path.rfind(":");
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return "";
} else {
return path.substr(0, i + 1);
@@ -759,7 +831,6 @@ std::string FilePath::canonicalize(std::string x) {
return x;
}
-
void FilePath::parse
(const std::string& filename,
std::string& root,
@@ -796,7 +867,7 @@ void FilePath::parse
}
- } else if ((f.size() >= 2) & isSlash(f[0]) && isSlash(f[1])) {
+ } else if ((f.size() >= 2) && isSlash(f[0]) && isSlash(f[1])) {
// e.g. //foo
root = f.substr(0, 2);
@@ -816,7 +887,7 @@ void FilePath::parse
if (i != std::string::npos) {
// Make sure it is after the last slash!
- size_t j = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t j = findLastSlash(f);
if ((j == std::string::npos) || (i > j)) {
ext = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
@@ -827,7 +898,7 @@ void FilePath::parse
// Pull the basename off
{
// Find the last slash
- size_t i = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t i = findLastSlash(f);
if (i == std::string::npos) {
@@ -860,7 +931,7 @@ void FilePath::parse
j = f.size();
}
- cur = iMin(i, j);
+ cur = min(i, j);
if (cur == std::string::npos) {
cur = f.size();
@@ -871,4 +942,86 @@ void FilePath::parse
}
}
+
+std::string FilePath::expandEnvironmentVariables(const std::string& path) {
+ // Search for pattern
+ size_t end = path.find_first_of('$', 0);
+ if (end == std::string::npos) {
+ // Pattern does not exist
+ return path;
+ }
+
+ size_t start = 0;
+ std::string result;
+ while (end != std::string::npos) {
+ const std::string& before = path.substr(start, end - start);
+ result += before;
+ start = end + 1;
+ std::string var;
+ if (path[start] == '(') {
+ // Search for close paren
+ end = path.find_first_of(')', start + 1);
+ if (end == std::string::npos) {
+ throw std::string("Missing close paren in environment variable in \"") + path + "\"";
+ }
+ var = path.substr(start + 1, end - start - 1);
+ } else {
+ // Search for slash or end of string
+ end = path.find_first_of('/', start);
+ size_t i = path.find_first_of('\\', start);
+ if ((size_t(i) != std::string::npos) && ((end == std::string::npos) || (size_t(i) < end))) {
+ end = i;
+ }
+ if (end == std::string::npos) {
+ // If the varible goes to the end of the string, it is the rest of the string
+ end = path.size();
+ } else {
+ --end;
+ }
+ var = path.substr(start, end - start + 1);
+ }
+
+ if (! var.empty()) {
+ const char* value = getenv(var.c_str());
+
+ if (value == NULL) {
+ throw (std::string("LocalLightingEnvironment variable \"") + var + "\" not defined for path \"" + path + "\"");
+ } else {
+ result += value;
+ }
+ } else {
+ // We just parsed an "empty" variable, which was probably a default share on Windows, e.g.,
+ // "\\mycomputer\c$", and not a variable name.
+ result += "$";
+ }
+
+ start = end + 1;
+ end = path.find_first_of('$', start);
+ }
+
+ // Paste on the remainder of the source path
+ if (start < path.size()) {
+ result += path.substr(start);
+ }
+
+ return result;
+}
+
+
+/** Generate a unique filename based on the provided hint */
+std::string FilePath::makeLegalFilename(const std::string& f, size_t maxLength) {
+ std::string tentative;
+
+ for (size_t i = 0; i < G3D::min(maxLength, f.size()); ++i) {
+ const char c = f[i];
+ if (isLetter(c) || isDigit(c) || (c == '-') || (c == '+') || (c == '=') || (c == '(') || (c == ')')) {
+ tentative += c;
+ } else {
+ tentative += "_";
+ }
+ }
+
+ return tentative;
+}
+
}
diff --git a/dep/g3dlite/source/GCamera.cpp b/dep/g3dlite/source/GCamera.cpp
deleted file mode 100644
index 0ffc7eb7374..00000000000
--- a/dep/g3dlite/source/GCamera.cpp
+++ /dev/null
@@ -1,511 +0,0 @@
-/**
- @file GCamera.cpp
-
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @author Jeff Marsceill, 08jcm@williams.edu
-
- @created 2005-07-20
- @edited 2010-02-22
-*/
-#include "G3D/GCamera.h"
-#include "G3D/platform.h"
-#include "G3D/Rect2D.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Ray.h"
-#include "G3D/Matrix4.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-GCamera::GCamera(const Any& any) {
- any.verifyName("GCamera");
- any.verifyType(Any::TABLE);
- *this = GCamera();
-
- const Any::AnyTable& table = any.table();
- Any::AnyTable::Iterator it = table.begin();
- while (it.hasMore()) {
- const std::string& k = toUpper(it->key);
- if (k == "FOVDIRECTION") {
- const std::string& v = toUpper(it->value);
- if (v == "HORIZONTAL") {
- m_direction = HORIZONTAL;
- } else if (v == "VERTICAL") {
- m_direction = VERTICAL;
- } else {
- any.verify(false, "fovDirection must be \"HORIZONTAL\" or \"VERTICAL\"");
- }
- } else if (k == "COORDINATEFRAME") {
- m_cframe = it->value;
- } else if (k == "FOVDEGREES") {
- m_fieldOfView = toRadians(it->value.number());
- } else if (k == "NEARPLANEZ") {
- m_nearPlaneZ = it->value;
- } else if (k == "FARPLANEZ") {
- m_farPlaneZ = it->value;
- } else if (k == "PIXELOFFSET") {
- m_pixelOffset = it->value;
- } else {
- any.verify(false, std::string("Illegal key in table: ") + it->key);
- }
- ++it;
- }
-}
-
-
-GCamera::operator Any() const {
- Any any(Any::TABLE, "GCamera");
-
- any.set("fovDirection", std::string((m_direction == HORIZONTAL) ? "HORIZONTAL" : "VERTICAL"));
- any.set("fovDegrees", toDegrees(m_fieldOfView));
- any.set("nearPlaneZ", nearPlaneZ());
- any.set("farPlaneZ", farPlaneZ());
- any.set("coordinateFrame", coordinateFrame());
- any.set("pixelOffset", pixelOffset());
-
- return any;
-}
-
-
-GCamera::GCamera() {
- setNearPlaneZ(-0.2f);
- setFarPlaneZ(-150.0f);
- setFieldOfView((float)toRadians(90.0f), HORIZONTAL);
-}
-
-
-GCamera::GCamera(const Matrix4& proj, const CFrame& frame) {
- float left, right, bottom, top, nearval, farval;
- proj.getPerspectiveProjectionParameters(left, right, bottom, top, nearval, farval);
- setNearPlaneZ(-nearval);
- setFarPlaneZ(-farval);
- float x = right;
-
- // Assume horizontal field of view
- setFieldOfView(atan2(x, -m_nearPlaneZ) * 2.0f, HORIZONTAL);
- setCoordinateFrame(frame);
-}
-
-
-GCamera::~GCamera() {
-}
-
-
-void GCamera::getCoordinateFrame(CoordinateFrame& c) const {
- c = m_cframe;
-}
-
-
-void GCamera::setCoordinateFrame(const CoordinateFrame& c) {
- m_cframe = c;
-}
-
-
-void GCamera::setFieldOfView(float angle, FOVDirection dir) {
- debugAssert((angle < pi()) && (angle > 0));
-
- m_fieldOfView = angle;
- m_direction = dir;
-}
-
-
-float GCamera::imagePlaneDepth() const{
- return -m_nearPlaneZ;
-}
-
-float GCamera::viewportWidth(const Rect2D& viewport) const {
- // Compute the side of a square at the near plane based on our field of view
- float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f);
-
- if (m_direction == VERTICAL) {
- s *= viewport.width() / viewport.height();
- }
-
- return s;
-}
-
-
-float GCamera::viewportHeight(const Rect2D& viewport) const {
- // Compute the side of a square at the near plane based on our field of view
- float s = 2.0f * -m_nearPlaneZ * tan(m_fieldOfView * 0.5f);
-
- debugAssert(m_fieldOfView < toRadians(180));
- if (m_direction == HORIZONTAL) {
- s *= viewport.height() / viewport.width();
- }
-
- return s;
-}
-
-
-Ray GCamera::worldRay(float x, float y, const Rect2D& viewport) const {
-
- int screenWidth = iFloor(viewport.width());
- int screenHeight = iFloor(viewport.height());
-
- Vector3 origin = m_cframe.translation;
-
- float cx = screenWidth / 2.0f;
- float cy = screenHeight / 2.0f;
-
- float vw = viewportWidth(viewport);
- float vh = viewportHeight(viewport);
-
- Vector3 direction = Vector3( (x - cx) * vw / screenWidth,
- -(y - cy) * vh / screenHeight,
- m_nearPlaneZ);
-
- direction = m_cframe.vectorToWorldSpace(direction);
-
- // Normalize the direction (we didn't do it before)
- direction = direction.direction();
-
- return Ray::fromOriginAndDirection(origin, direction);
-}
-
-
-void GCamera::getProjectPixelMatrix(const Rect2D& viewport, Matrix4& P) const {
- getProjectUnitMatrix(viewport, P);
- float screenWidth = viewport.width();
- float screenHeight = viewport.height();
-
- float sx = screenWidth / 2.0;
- float sy = screenHeight / 2.0;
-
- P = Matrix4(sx, 0, 0, sx + viewport.x0() - m_pixelOffset.x,
- 0, -sy, 0, sy + viewport.y0() + m_pixelOffset.y,
- 0, 0, 1, 0,
- 0, 0, 0, 1) * P;
-}
-
-
-void GCamera::getProjectUnitMatrix(const Rect2D& viewport, Matrix4& P) const {
-
- float screenWidth = viewport.width();
- float screenHeight = viewport.height();
-
- float r, l, t, b, n, f, x, y;
-
- float s = 1.0f;
- if (m_direction == VERTICAL) {
- y = -m_nearPlaneZ * tan(m_fieldOfView / 2);
- x = y * (screenWidth / screenHeight);
- s = screenHeight;
- } else { //m_direction == HORIZONTAL
- x = -m_nearPlaneZ * tan(m_fieldOfView / 2);
- y = x * (screenHeight / screenWidth);
- s = screenWidth;
- }
-
- n = -m_nearPlaneZ;
- f = -m_farPlaneZ;
- r = x - m_pixelOffset.x/s;
- l = -x - m_pixelOffset.x/s;
- t = y + m_pixelOffset.y/s;
- b = -y + m_pixelOffset.y/s;
-
- P = Matrix4::perspectiveProjection(l, r, b, t, n, f);
-}
-
-
-Vector3 GCamera::projectUnit(const Vector3& point, const Rect2D& viewport) const {
- Matrix4 M;
- getProjectUnitMatrix(viewport, M);
-
- Vector4 cameraSpacePoint(coordinateFrame().pointToObjectSpace(point), 1.0f);
- const Vector4& screenSpacePoint = M * cameraSpacePoint;
-
- return Vector3(screenSpacePoint.xyz() / screenSpacePoint.w);
-}
-
-Vector3 GCamera::project(const Vector3& point,
- const Rect2D& viewport) const {
-
- // Find the point in the homogeneous cube
- const Vector3& cube = projectUnit(point, viewport);
-
- return convertFromUnitToNormal(cube, viewport);
-}
-
-Vector3 GCamera::unprojectUnit(const Vector3& v, const Rect2D& viewport) const {
-
- const Vector3& projectedPoint = convertFromUnitToNormal(v, viewport);
-
- return unproject(projectedPoint, viewport);
-}
-
-
-Vector3 GCamera::unproject(const Vector3& v, const Rect2D& viewport) const {
-
- const float n = m_nearPlaneZ;
- const float f = m_farPlaneZ;
-
- float z;
-
- if (-f >= finf()) {
- // Infinite far plane
- z = 1.0f / (((-1.0f / n) * v.z) + 1.0f / n);
- } else {
- z = 1.0f / ((((1.0f / f) - (1.0f / n)) * v.z) + 1.0f / n);
- }
-
- const Ray& ray = worldRay(v.x - m_pixelOffset.x, v.y - m_pixelOffset.y, viewport);
-
- // Find out where the ray reaches the specified depth.
- const Vector3& out = ray.origin() + ray.direction() * -z / (ray.direction().dot(m_cframe.lookVector()));
-
- return out;
-}
-
-
-float GCamera::worldToScreenSpaceArea(float area, float z, const Rect2D& viewport) const {
- (void)viewport;
- if (z >= 0) {
- return finf();
- }
- return area * (float)square(imagePlaneDepth() / z);
-}
-
-
-void GCamera::getClipPlanes(
- const Rect2D& viewport,
- Array<Plane>& clip) const {
-
- Frustum fr;
- frustum(viewport, fr);
- clip.resize(fr.faceArray.size(), DONT_SHRINK_UNDERLYING_ARRAY);
- for (int f = 0; f < clip.size(); ++f) {
- clip[f] = fr.faceArray[f].plane;
- }
-}
-
-
-GCamera::Frustum GCamera::frustum(const Rect2D& viewport) const {
- Frustum f;
- frustum(viewport, f);
- return f;
-}
-
-
-void GCamera::frustum(const Rect2D& viewport, Frustum& fr) const {
-
- // The volume is the convex hull of the vertices definining the view
- // frustum and the light source point at infinity.
-
- const float x = viewportWidth(viewport) / 2;
- const float y = viewportHeight(viewport) / 2;
- const float zn = m_nearPlaneZ;
- const float zf = m_farPlaneZ;
- float xx, zz, yy;
-
- float halfFOV = m_fieldOfView * 0.5f;
-
- // This computes the normal, which is based on the complement of the
- // halfFOV angle, so the equations are "backwards"
- if (m_direction == VERTICAL) {
- yy = -cosf(halfFOV);
- xx = yy * viewport.height() / viewport.width();
- zz = -sinf(halfFOV);
- } else {
- xx = -cosf(halfFOV);
- yy = xx * viewport.width() / viewport.height();
- zz = -sinf(halfFOV);
- }
-
- // Near face (ccw from UR)
- fr.vertexPos.append(
- Vector4( x, y, zn, 1),
- Vector4(-x, y, zn, 1),
- Vector4(-x, -y, zn, 1),
- Vector4( x, -y, zn, 1));
-
- // Far face (ccw from UR, from origin)
- if (m_farPlaneZ == -finf()) {
- fr.vertexPos.append(Vector4( x, y, zn, 0),
- Vector4(-x, y, zn, 0),
- Vector4(-x, -y, zn, 0),
- Vector4( x, -y, zn, 0));
- } else {
- // Finite
- const float s = zf / zn;
- fr.vertexPos.append(Vector4( x * s, y * s, zf, 1),
- Vector4(-x * s, y * s, zf, 1),
- Vector4(-x * s, -y * s, zf, 1),
- Vector4( x * s, -y * s, zf, 1));
- }
-
- Frustum::Face face;
-
- // Near plane (wind backwards so normal faces into frustum)
- // Recall that nearPlane, farPlane are positive numbers, so
- // we need to negate them to produce actual z values.
- face.plane = Plane(Vector3(0,0,-1), Vector3(0,0,m_nearPlaneZ));
- face.vertexIndex[0] = 3;
- face.vertexIndex[1] = 2;
- face.vertexIndex[2] = 1;
- face.vertexIndex[3] = 0;
- fr.faceArray.append(face);
-
- // Right plane
- face.plane = Plane(Vector3(xx, 0, zz), Vector3::zero());
- face.vertexIndex[0] = 0;
- face.vertexIndex[1] = 4;
- face.vertexIndex[2] = 7;
- face.vertexIndex[3] = 3;
- fr.faceArray.append(face);
-
- // Left plane
- face.plane = Plane(Vector3(-fr.faceArray.last().plane.normal().x, 0, fr.faceArray.last().plane.normal().z), Vector3::zero());
- face.vertexIndex[0] = 5;
- face.vertexIndex[1] = 1;
- face.vertexIndex[2] = 2;
- face.vertexIndex[3] = 6;
- fr.faceArray.append(face);
-
- // Top plane
- face.plane = Plane(Vector3(0, yy, zz), Vector3::zero());
- face.vertexIndex[0] = 1;
- face.vertexIndex[1] = 5;
- face.vertexIndex[2] = 4;
- face.vertexIndex[3] = 0;
- fr.faceArray.append(face);
-
- // Bottom plane
- face.plane = Plane(Vector3(0, -fr.faceArray.last().plane.normal().y, fr.faceArray.last().plane.normal().z), Vector3::zero());
- face.vertexIndex[0] = 2;
- face.vertexIndex[1] = 3;
- face.vertexIndex[2] = 7;
- face.vertexIndex[3] = 6;
- fr.faceArray.append(face);
-
- // Far plane
- if (-m_farPlaneZ < finf()) {
- face.plane = Plane(Vector3(0, 0, 1), Vector3(0, 0, m_farPlaneZ));
- face.vertexIndex[0] = 4;
- face.vertexIndex[1] = 5;
- face.vertexIndex[2] = 6;
- face.vertexIndex[3] = 7;
- fr.faceArray.append(face);
- }
-
- // Transform vertices to world space
- for (int v = 0; v < fr.vertexPos.size(); ++v) {
- fr.vertexPos[v] = m_cframe.toWorldSpace(fr.vertexPos[v]);
- }
-
- // Transform planes to world space
- for (int p = 0; p < fr.faceArray.size(); ++p) {
- // Since there is no scale factor, we don't have to
- // worry about the inverse transpose of the normal.
- Vector3 normal;
- float d;
-
- fr.faceArray[p].plane.getEquation(normal, d);
-
- Vector3 newNormal = m_cframe.rotation * normal;
-
- if (isFinite(d)) {
- d = (newNormal * -d + m_cframe.translation).dot(newNormal);
- fr.faceArray[p].plane = Plane(newNormal, newNormal * d);
- } else {
- // When d is infinite, we can't multiply 0's by it without
- // generating NaNs.
- fr.faceArray[p].plane = Plane::fromEquation(newNormal.x, newNormal.y, newNormal.z, d);
- }
- }
-}
-
-void GCamera::getNearViewportCorners
-(const Rect2D& viewport,
- Vector3& outUR,
- Vector3& outUL,
- Vector3& outLL,
- Vector3& outLR) const {
-
- // Must be kept in sync with getFrustum()
- const float w = viewportWidth(viewport) / 2.0f;
- const float h = viewportHeight(viewport) / 2.0f;
- const float z = nearPlaneZ();
-
- // Compute the points
- outUR = Vector3( w, h, z);
- outUL = Vector3(-w, h, z);
- outLL = Vector3(-w, -h, z);
- outLR = Vector3( w, -h, z);
-
- // Take to world space
- outUR = m_cframe.pointToWorldSpace(outUR);
- outUL = m_cframe.pointToWorldSpace(outUL);
- outLR = m_cframe.pointToWorldSpace(outLR);
- outLL = m_cframe.pointToWorldSpace(outLL);
-}
-
-void GCamera::getFarViewportCorners(
- const Rect2D& viewport,
- Vector3& outUR,
- Vector3& outUL,
- Vector3& outLL,
- Vector3& outLR) const {
-
- // Must be kept in sync with getFrustum()
- const float w = viewportWidth(viewport) * m_farPlaneZ / m_nearPlaneZ;
- const float h = viewportHeight(viewport) * m_farPlaneZ / m_nearPlaneZ;
- const float z = m_farPlaneZ;
-
- // Compute the points
- outUR = Vector3( w/2, h/2, z);
- outUL = Vector3(-w/2, h/2, z);
- outLL = Vector3(-w/2, -h/2, z);
- outLR = Vector3( w/2, -h/2, z);
-
- // Take to world space
- outUR = m_cframe.pointToWorldSpace(outUR);
- outUL = m_cframe.pointToWorldSpace(outUL);
- outLR = m_cframe.pointToWorldSpace(outLR);
- outLL = m_cframe.pointToWorldSpace(outLL);
-}
-
-
-
-void GCamera::setPosition(const Vector3& t) {
- m_cframe.translation = t;
-}
-
-
-void GCamera::lookAt(const Vector3& position, const Vector3& up) {
- m_cframe.lookAt(position, up);
-}
-
-
-void GCamera::serialize(BinaryOutput& bo) const {
- bo.writeFloat32(m_fieldOfView);
- bo.writeFloat32(imagePlaneDepth());
- debugAssert(nearPlaneZ() < 0.0f);
- bo.writeFloat32(nearPlaneZ());
- debugAssert(farPlaneZ() < 0.0f);
- bo.writeFloat32(farPlaneZ());
- m_cframe.serialize(bo);
- bo.writeInt8(m_direction);
- m_pixelOffset.serialize(bo);
-}
-
-
-void GCamera::deserialize(BinaryInput& bi) {
- m_fieldOfView = bi.readFloat32();
- m_nearPlaneZ = bi.readFloat32();
- debugAssert(m_nearPlaneZ < 0.0f);
- m_farPlaneZ = bi.readFloat32();
- debugAssert(m_farPlaneZ < 0.0f);
- m_cframe.deserialize(bi);
- m_direction = (FOVDirection)bi.readInt8();
- m_pixelOffset.deserialize(bi);
-}
-
-
-Vector3 GCamera::convertFromUnitToNormal(const Vector3& in, const Rect2D& viewport) const{
- return (in + Vector3(1,1,1)) * 0.5 * Vector3(viewport.width(), -viewport.height(), 1) +
- Vector3(viewport.x0(), viewport.y1(), 0);
-}
-} // namespace
diff --git a/dep/g3dlite/source/GImage.cpp b/dep/g3dlite/source/GImage.cpp
deleted file mode 100644
index 19a2b1e71f4..00000000000
--- a/dep/g3dlite/source/GImage.cpp
+++ /dev/null
@@ -1,1166 +0,0 @@
-/**
- \file GImage.cpp
- \author Morgan McGuire, http://graphics.cs.williams.edu
- Copyright 2002-2010, Morgan McGuire
-
- \created 2002-05-27
- \edited 2010-01-04
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/debug.h"
-#include "G3D/stringutils.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-#include "G3D/fileutils.h"
-
-#ifdef G3D_LINUX
-# include <png.h>
-#else
-# include "png.h"
-#endif
-
-#include <sys/stat.h>
-#include <assert.h>
-#include <sys/types.h>
-
-//////////////////////////////////////////////////////////////////////////////////////////////
-
-namespace G3D {
-
-void GImage::LtoRGBA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int v = in[i];
- int i4 = i * 4;
-
- out[i4 + 0] = v;
- out[i4 + 1] = v;
- out[i4 + 2] = v;
- out[i4 + 3] = 255;
- }
-}
-
-
-void GImage::LtoRGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int v = in[i];
- int i3 = i * 3;
-
- out[i3 + 0] = v;
- out[i3 + 1] = v;
- out[i3 + 2] = v;
- }
-}
-
-
-void GImage::RGBtoRGBA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = in[i3 + 0];
- out[i4 + 1] = in[i3 + 1];
- out[i4 + 2] = in[i3 + 2];
- out[i4 + 3] = 255;
- }
-}
-
-
-void GImage::RGBAtoRGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i3 + 0] = in[i4 + 0];
- out[i3 + 1] = in[i4 + 1];
- out[i3 + 2] = in[i4 + 2];
- }
-}
-
-
-void GImage::RGBtoBGRA(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 2] = in[i3 + 0];
- out[i4 + 1] = in[i3 + 1];
- out[i4 + 0] = in[i3 + 2];
- out[i4 + 3] = 255;
- }
-}
-
-
-
-void GImage::RGBtoBGR(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
-
- int r = in[i3 + 0];
- int g = in[i3 + 1];
- int b = in[i3 + 2];
-
- out[i3 + 2] = r;
- out[i3 + 1] = g;
- out[i3 + 0] = b;
- }
-}
-
-
-void GImage::RGBxRGBtoRGBA(
- const uint8* colorRGB,
- const uint8* alphaRGB,
- uint8* out,
- int numPixels) {
-
- for (int i = numPixels - 1; i >= 0; --i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = colorRGB[i3 + 0];
- out[i4 + 1] = colorRGB[i3 + 1];
- out[i4 + 2] = colorRGB[i3 + 2];
- out[i4 + 3] = alphaRGB[i3 + 0];
- }
-}
-
-
-void GImage::RGBtoARGB(
- const uint8* in,
- uint8* out,
- int numPixels) {
-
- for (int i = 0; i < numPixels; ++i) {
- int i3 = i * 3;
- int i4 = i3 + i;
-
- out[i4 + 0] = 255;
- out[i4 + 1] = in[i3 + 0];
- out[i4 + 2] = in[i3 + 1];
- out[i4 + 3] = in[i3 + 2];
- }
-}
-
-
-void GImage::flipRGBVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height) {
-
-
- // Allocate a temp row so the operation
- // is still safe if in == out
- uint8* temp = (uint8*)System::malloc(width * 3);
- alwaysAssertM(temp != NULL, "Out of memory");
-
- int oneRow = width * 3;
- int N = height / 2;
-
- // if height is an odd value, don't swap odd middle row
- for (int i = 0; i < N; ++i) {
- int topOff = i * oneRow;
- int botOff = (height - i - 1) * oneRow;
- System::memcpy(temp, in + topOff, oneRow);
- System::memcpy(out + topOff, in + botOff, oneRow);
- System::memcpy(out + botOff, temp, oneRow);
- }
-
- System::free(temp);
-}
-
-
-void GImage::flipRGBAVertical(
- const uint8* in,
- uint8* out,
- int width,
- int height) {
-
-
- // Allocate a temp row so the operation
- // is still safe if in == out
- uint8* temp = (uint8*)System::malloc(width * 4);
- alwaysAssertM(temp != NULL, "Out of memory");
-
- int oneRow = width * 4;
-
- // if height is an odd value, don't swap odd middle row
- for (int i = 0; i < height / 2; ++i) {
- int topOff = i * oneRow;
- int botOff = (height - i - 1) * oneRow;
- System::memcpy(temp, in + topOff, oneRow);
- System::memcpy(out + topOff, in + botOff, oneRow);
- System::memcpy(out + botOff, temp, oneRow);
- }
-
- System::free(temp);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-void GImage::decode(
- BinaryInput& input,
- Format format) {
-
- switch (format) {
- case PPM_ASCII:
- decodePPMASCII(input);
- break;
-
- case PPM_BINARY:
- decodePPM(input);
- break;
-
- case PNG:
- decodePNG(input);
- break;
-
- case JPEG:
- decodeJPEG(input);
- break;
-
- case TGA:
- decodeTGA(input);
- break;
-
- case BMP:
- decodeBMP(input);
- break;
-
- case ICO:
- decodeICO(input);
- break;
-
- case PCX:
- decodePCX(input);
- break;
-
- default:
- debugAssert(false);
- }
-
- debugAssert(m_width >= 0);
- debugAssert(m_height >= 0);
- debugAssert(m_channels == 1 || m_channels == 3 || m_channels == 4);
- debugAssert(m_byte != NULL);
-}
-
-
-void GImage::decodePCX(
- BinaryInput& input) {
-
- uint8 manufacturer = input.readUInt8();
- uint8 version = input.readUInt8();
- uint8 encoding = input.readUInt8();
- uint8 bitsPerPixel = input.readUInt8();
-
- uint16 xmin = input.readUInt16();
- uint16 ymin = input.readUInt16();
- uint16 xmax = input.readUInt16();
- uint16 ymax = input.readUInt16();
-
- uint16 horizDPI = input.readUInt16();
- uint16 vertDPI = input.readUInt16();
-
- Color3uint8 colorMap[16];
- input.readBytes(colorMap, 48);
-
- input.skip(1);
-
- uint8 planes = input.readUInt8();
- uint16 bytesPerLine = input.readUInt16();
- uint16 paletteType = input.readUInt16();
- input.skip(4 + 54);
-
- (void)bytesPerLine;
-
- m_width = xmax - xmin + 1;
- m_height = ymax - ymin + 1;
- m_channels = 3;
-
- if ((manufacturer != 0x0A) || (encoding != 0x01)) {
- throw GImage::Error("PCX file is corrupted", input.getFilename());
- }
-
- (void)version;
- (void)vertDPI;
- (void)horizDPI;
-
- if ((bitsPerPixel != 8) || ((planes != 1) && (planes != 3))) {
- throw GImage::Error("Only 8-bit paletted and 24-bit PCX files supported.", input.getFilename());
- }
-
- // Prepare the pointer object for the pixel data
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- if ((paletteType == 1) && (planes == 3)) {
-
- Color3uint8* pixel = pixel3();
-
- // Iterate over each scan line
- for (int row = 0; row < m_height; ++row) {
- // Read each scan line once per plane
- for (int plane = 0; plane < planes; ++plane) {
- int p = row * m_width;
- int p1 = p + m_width;
- while (p < p1) {
- uint8 value = input.readUInt8();
- int length = 1;
-
- if (value >= 192) {
- // This is the length, not the value. Mask off
- // the two high bits and read the true index.
- length = value & 0x3F;
- value = input.readUInt8();
- }
-
- // Set the whole run
- for (int i = length - 1; i >= 0; --i, ++p) {
- debugAssert(p < m_width * m_height);
- pixel[p][plane] = value;
- }
- }
- }
- }
-
- } else if (planes == 1) {
-
- Color3uint8 palette[256];
-
- int imageBeginning = input.getPosition();
- int paletteBeginning = input.getLength() - 769;
-
- input.setPosition(paletteBeginning);
-
- uint8 dummy = input.readUInt8();
-
- if (dummy != 12) {
- Log::common()->println("\n*********************");
- Log::common()->printf("Warning: Corrupted PCX file (palette marker byte was missing) \"%s\"\nLoading anyway\n\n", input.getFilename().c_str());
- }
-
- input.readBytes(palette, sizeof(palette));
- input.setPosition(imageBeginning);
-
- Color3uint8* pixel = pixel3();
-
- // The palette indices are run length encoded.
- int p = 0;
- while (p < m_width * m_height) {
- uint8 index = input.readUInt8();
- uint8 length = 1;
-
- if (index >= 192) {
- // This is the length, not the index. Mask off
- // the two high bits and read the true index.
- length = index & 0x3F;
- index = input.readUInt8();
- }
-
- Color3uint8 color = palette[index];
-
- // Set the whole run
- for (int i = length - 1; i >= 0; --i, ++p) {
- if (p > m_width * m_height) {
- break;
- }
- pixel[p] = color;
- }
-
- }
-
- } else {
- throw GImage::Error("Unsupported PCX file type.", input.getFilename());
- }
-}
-
-
-GImage::Format GImage::resolveFormat(const std::string& filename) {
- BinaryInput b(filename, G3D_LITTLE_ENDIAN);
- if (b.size() <= 0) {
- throw Error("File not found.", filename);
- }
-
- return resolveFormat(filename, b.getCArray(), b.size(), AUTODETECT);
-}
-
-
-GImage::Format GImage::resolveFormat(
- const std::string& filename,
- const uint8* data,
- int dataLen,
- Format maybeFormat) {
-
- // Return the provided format if it is specified.
- if (maybeFormat != AUTODETECT) {
- return maybeFormat;
- }
-
- std::string extension = toUpper(filenameExt(filename));
-
- if ((extension == "PPM") || (extension == "PGM") || (extension == "PBM")) {
- // There are two PPM formats (binary and ASCII); we handle them differently
- if (dataLen > 3) {
- if (!memcmp(data, "P6", 2) || !memcmp(data, "P5", 2)) {
- return PPM_BINARY;
- } else {
- return PPM_ASCII;
- }
- }
- }
-
- Format tmp = stringToFormat(extension);
- if ((tmp != AUTODETECT) && (tmp != UNKNOWN)) {
- return tmp;
- }
-
- // Try and autodetect from the file itself by looking at the first
- // character.
-
- // We can't look at the character if it is null.
- debugAssert(data != NULL);
-
- if ((dataLen > 3) && (! memcmp(data, "P3", 2) || (! memcmp(data, "P2", 2)) || (! memcmp(data, "P1", 2)))) {
- return PPM_ASCII;
- }
-
- if ((dataLen > 3) && (!memcmp(data, "P6", 2) ||!memcmp(data, "P5", 2))) {
- return PPM_BINARY;
- }
-
- if (dataLen > 8) {
- if (!png_sig_cmp((png_bytep)data, 0, 8)) {
- return PNG;
- }
- }
-
- if ((dataLen > 0) && (data[0] == 'B')) {
- return BMP;
- }
-
- if (dataLen > 10) {
- if ((dataLen > 11) && (data[0] == 0xFF) &&
- (memcmp(&data[6], "JFIF", 4) == 0)) {
- return JPEG;
- }
- }
-
- if (dataLen > 40) {
- if (memcmp(&data[dataLen - 18], "TRUEVISION-XFILE", 16) == 0) {
- return TGA;
- }
- }
-
- if ((dataLen > 4) && (data[0] == 0) && (data[1] == 0) && (data[2] == 0) && (data[3] == 1)) {
- return ICO;
- }
-
- if ((dataLen > 0) && (data[0] == 10)) {
- return PCX;
- }
-
- return UNKNOWN;
-}
-
-
-GImage::GImage(
- const std::string& filename,
- Format format,
- const MemoryManager::Ref& m) :
- m_memMan(m),
- m_byte(NULL),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- load(filename, format);
-}
-
-
-void GImage::load(
- const std::string& filename,
- Format format) {
-
- clear();
-
- try {
- BinaryInput b(filename, G3D_LITTLE_ENDIAN);
- if (b.size() <= 0) {
- throw Error("File not found.", filename);
- }
-
- alwaysAssertM(this != NULL, "Corrupt GImage");
- decode(b, resolveFormat(filename, b.getCArray(), b.size(), format));
- } catch (const std::string& error) {
- throw Error(error, filename);
- }
-}
-
-
-GImage::GImage(
- const uint8* data,
- int length,
- Format format,
- const MemoryManager::Ref& m) :
- m_memMan(m),
- m_byte(NULL),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- BinaryInput b(data, length, G3D_LITTLE_ENDIAN);
- // It is safe to cast away the const because we
- // know we don't corrupt the data.
-
- decode(b, resolveFormat("", data, length, format));
-}
-
-
-GImage::GImage(
- int width,
- int height,
- int channels,
- const MemoryManager::Ref& mem) :
- m_memMan(mem),
- m_byte(0),
- m_channels(0),
- m_width(0),
- m_height(0) {
-
- resize(width, height, channels);
-}
-
-
-void GImage::resize(
- int width,
- int height,
- int channels,
- bool zero) {
-
- debugAssert(width >= 0);
- debugAssert(height >= 0);
- debugAssert(channels >= 1);
-
- clear();
-
- m_width = width;
- m_height = height;
- m_channels = channels;
- size_t sz = width * height * channels;
-
- if (sz > 0) {
- m_byte = (uint8*)m_memMan->alloc(sz);
- if (zero) {
- System::memset(m_byte, 0, sz);
- }
- debugAssert(isValidHeapPointer(m_byte));
- }
-}
-
-
-void GImage::_copy(
- const GImage& other) {
-
- clear();
-
- m_width = other.m_width;
- m_height = other.m_height;
- m_channels = other.m_channels;
- int s = m_width * m_height * m_channels * sizeof(uint8);
- m_byte = (uint8*)m_memMan->alloc(s);
- debugAssert(isValidHeapPointer(m_byte));
- memcpy(m_byte, other.m_byte, s);
-}
-
-
-void GImage::flipHorizontal() {
- uint8 temp[4];
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- uint8* row = m_byte + y * rowBytes;
- for (int x = 0; x < m_width / 2; ++x) {
- System::memcpy(temp, row + x * m_channels, m_channels);
- System::memcpy(row + x * m_channels, row + (m_width - x - 1) * m_channels, m_channels);
- System::memcpy(row + (m_width - x - 1) * m_channels, temp, m_channels);
- }
- }
-}
-
-
-void GImage::flipVertical() {
- uint8* old = m_byte;
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
-
- // We could do this with only a single-row temp buffer, but then
- // we'd have to copy twice as much data.
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- System::memcpy(m_byte + y * rowBytes, old + (m_height - y - 1) * rowBytes, rowBytes);
- }
-
- m_memMan->free(old);
-}
-
-
-void GImage::rotate90CW(int numTimes) {
-
- uint8* old = NULL;
- numTimes = iWrap(numTimes, 4);
- if (numTimes > 0) {
- (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- }
- for (int j = 0; j < numTimes; ++j) {
- {
- uint8* temp = old;
- old = m_byte;
- m_byte = temp;
- }
-
- {
- int temp = m_width;
- m_width = m_height;
- m_height = temp;
- }
-
- int rowBytes = m_width * m_channels;
- for (int y = 0; y < m_height; ++y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* dst = m_byte + x + y * rowBytes;
- uint8* src = old + y + (m_height - x - 1) * rowBytes;
- System::memcpy(dst, src, m_channels);
- }
- }
- }
- m_memMan->free(old);
-}
-
-
-
-GImage::GImage(
- const GImage& other,
- const MemoryManager::Ref& m) : m_memMan(m), m_byte(NULL) {
-
- _copy(other);
-}
-
-
-GImage::~GImage() {
- clear();
-}
-
-
-void GImage::clear() {
- m_width = 0;
- m_height = 0;
- m_memMan->free(m_byte);
- m_byte = NULL;
-}
-
-
-GImage& GImage::operator=(const GImage& other) {
- _copy(other);
- return *this;
-}
-
-
-bool GImage::copySubImage(
- GImage & dest, const GImage & src,
- int srcX, int srcY, int srcWidth, int srcHeight) {
- if ((src.m_width < srcX + srcWidth) ||
- (src.m_height < srcY + srcHeight) ||
- (srcY < 0) ||
- (srcX < 0)) {
-
- return false;
- }
-
- dest.resize(srcWidth, srcHeight, src.m_channels);
-
- bool ret;
- ret = pasteSubImage(dest, src, 0, 0, srcX, srcY, srcWidth, srcHeight);
- debugAssert(ret);
-
- return true;
-}
-
-
-bool GImage::pasteSubImage(
- GImage & dest, const GImage & src,
- int destX, int destY,
- int srcX, int srcY, int srcWidth, int srcHeight) {
-
- if ((src.m_width < srcX + srcWidth) ||
- (src.m_height < srcY + srcHeight) ||
- (dest.m_width < destX + srcWidth) ||
- (dest.m_height < destY + srcHeight) ||
- (srcY < 0) ||
- (srcX < 0) ||
- (destY < 0) ||
- (destX < 0) ||
- (src.channels() != dest.channels())) {
-
- return false;
- }
-
- for (int i = 0; i < srcHeight; i++) {
- const uint8* srcRow = src.byte() +
- ((i + srcY) * src.m_width + srcX) * src.channels();
- uint8* destRow = dest.byte() +
- ((i + destY) * dest.width() + destX) * dest.channels();
- memcpy(destRow, srcRow, srcWidth * src.m_channels);
- }
-
- return true;
-}
-
-
-bool GImage::supportedFormat(
- const std::string& format) {
-
- return (stringToFormat(format) != UNKNOWN);
-}
-
-
-GImage::Format GImage::stringToFormat(
- const std::string& format) {
-
- std::string extension = toUpper(format);
-
- if ((extension == "JPG") || (extension == "JPEG")) {
- return JPEG;
- } else if (extension == "TGA") {
- return TGA;
- } else if (extension == "BMP") {
- return BMP;
- } else if (extension == "PCX") {
- return PCX;
- } else if (extension == "ICO") {
- return ICO;
- } else if (extension == "PNG") {
- return PNG;
- } else {
- return UNKNOWN;
- }
- // Don't put PPM here, since it has two versions
-}
-
-
-void GImage::save(
- const std::string& filename,
- Format format) const {
-
- BinaryOutput b(filename, G3D_LITTLE_ENDIAN);
- encode(resolveFormat(filename, NULL, 0, format), b);
- b.commit(false);
-}
-
-
-void GImage::encode(
- Format format,
- uint8*& outData,
- int& outLength) const {
-
- BinaryOutput out;
-
- encode(format, out);
-
- outData = (uint8*)System::malloc(out.size());
- debugAssert(outData);
- outLength = out.size();
-
- out.commit(outData);
-}
-
-
-void GImage::encode(
- Format format,
- BinaryOutput& out) const {
-
- switch (format) {
- case PPM_ASCII:
- encodePPMASCII(out);
- break;
-
- case PPM_BINARY:
- encodePPM(out);
- break;
-
- case PNG:
- encodePNG(out);
- break;
-
- case JPEG:
- encodeJPEG(out);
- break;
-
- case BMP:
- encodeBMP(out);
- break;
-
- case TGA:
- encodeTGA(out);
- break;
-
- default:
- debugAssert(false);
- }
-}
-
-
-void GImage::insertRedAsAlpha(const GImage& alpha, GImage& output) const {
- debugAssert(alpha.width() == width());
- debugAssert(alpha.height() == height());
-
- // make sure output GImage is valid
- if (output.width() != width() || output.height() != height() || output.channels() != 4) {
- output.resize(width(), height(), 4);
- }
-
- int N = m_width * m_height;
- for (int i = 0; i < N; ++i) {
- output.byte()[i * 4 + 0] = byte()[i * m_channels + 0];
- output.byte()[i * 4 + 1] = byte()[i * m_channels + 1];
- output.byte()[i * 4 + 2] = byte()[i * m_channels + 2];
- output.byte()[i * 4 + 3] = alpha.byte()[i * alpha.m_channels];
- }
-}
-
-
-void GImage::stripAlpha(GImage& output) const {
-
- if (output.m_width != m_width || output.m_height != m_height || output.m_channels != 3) {
- output.resize(m_width, m_height, 3);
- }
-
- int N = m_width * m_height;
- for (int i = 0; i < N; ++i) {
- output.byte()[i * 3 + 0] = byte()[i * m_channels + 0];
- output.byte()[i * 3 + 1] = byte()[i * m_channels + 1];
- output.byte()[i * 3 + 2] = byte()[i * m_channels + 2];
- }
-}
-
-
-int GImage::sizeInMemory() const {
- return sizeof(GImage) + m_width * m_height * m_channels;
-}
-
-
-void GImage::computeNormalMap(
- const GImage& bump,
- GImage& normal,
- const BumpMapPreprocess& preprocess) {
- computeNormalMap(bump.m_width, bump.m_height, bump.m_channels,
- bump.byte(), normal, preprocess);
-}
-
-void GImage::computeNormalMap(
- int width,
- int height,
- int channels,
- const uint8* src,
- GImage& normal,
- const BumpMapPreprocess& preprocess) {
-
- float whiteHeightInPixels = preprocess.zExtentPixels;
- bool lowPassBump = preprocess.lowPassFilter;
- bool scaleHeightByNz = preprocess.scaleZByNz;
-
- if (whiteHeightInPixels < 0.0f) {
- // Default setting scales so that a gradient ramp
- // over the whole image becomes a 45-degree angle
-
- // Account for potentially non-square aspect ratios
- whiteHeightInPixels = max(width, height) * -whiteHeightInPixels;
- }
-
- debugAssert(whiteHeightInPixels >= 0);
-
- const int w = width;
- const int h = height;
- const int stride = channels;
-
- normal.resize(w, h, 4);
-
- const uint8* const B = src;
- Color4uint8* const N = normal.pixel4();
-
- // 1/s for the scale factor that each ELEVATION should be multiplied by.
- // We avoid actually multiplying by this and instead just divide it out of z.
- float elevationInvScale = 255.0f / whiteHeightInPixels;
-
- for (int y = 0; y < h; ++y) {
- for (int x = 0; x < w; ++x) {
- // Index into normal map pixel
- int i = x + y * w;
-
- // Index into bump map *byte*
- int j = stride * i;
-
- Vector3 delta;
-
- // Get a value from B (with wrapping lookup) relative to (x, y)
- // and divide by 255
- #define ELEVATION(DX, DY) ((int)B[(((DX + x + w) % w) + \
- ((DY + y + h) % h) * w) * stride])
-
-
- // Sobel filter to compute the normal.
- //
- // Y Filter (X filter is the transpose)
- // [ -1 -2 -1 ]
- // [ 0 0 0 ]
- // [ 1 2 1 ]
-
- // Write the Y value directly into the x-component so we don't have
- // to explicitly compute a cross product at the end. Does not
- // go out of bounds because the above is computed mod (width, height)
- delta.y = -( ELEVATION(-1, -1) * 1 + ELEVATION( 0, -1) * 2 + ELEVATION( 1, -1) * 1 +
- -ELEVATION(-1, 1) * 1 + -ELEVATION( 0, 1) * 2 + -ELEVATION( 1, 1) * 1);
-
- delta.x = -(-ELEVATION(-1, -1) * 1 + ELEVATION( 1, -1) * 1 +
- -ELEVATION(-1, 0) * 2 + ELEVATION( 1, 0) * 2 +
- -ELEVATION(-1, 1) * 1 + ELEVATION( 1, 1) * 1);
-
- // The scale of each filter row is 4, the filter width is two pixels,
- // and the "normal" range is 0-255.
- delta.z = 4 * 2 * elevationInvScale;
-
- // Delta is now scaled in pixels; normalize
- delta = delta.direction();
-
- // Copy over the bump value into the alpha channel.
- float H = B[j] / 255.0f;
-
- if (lowPassBump) {
- H = (ELEVATION(-1, -1) + ELEVATION( 0, -1) + ELEVATION(1, -1) +
- ELEVATION(-1, 0) + ELEVATION( 0, 0) + ELEVATION(1, 0) +
- ELEVATION(-1, 1) + ELEVATION( 0, 1) + ELEVATION(1, 1)) / (255.0f * 9.0f);
- }
-# undef ELEVATION
-
- if (scaleHeightByNz) {
- // delta.z can't possibly be negative, so we avoid actually
- // computing the absolute value.
- H *= delta.z;
- }
-
- N[i].a = iRound(H * 255.0f);
-
- // Pack into byte range
- delta = delta * 127.5f + Vector3(127.5f, 127.5f, 127.5f);
- N[i].r = iClamp(iRound(delta.x), 0, 255);
- N[i].g = iClamp(iRound(delta.y), 0, 255);
- N[i].b = iClamp(iRound(delta.z), 0, 255);
- }
- }
-}
-
-
-/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
-
-void GImage::convertToL8() {
- switch (m_channels) {
- case 1:
- return;
-
- case 3:
- {
- // Average
- Color3uint8* src = (Color3uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 1);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color3uint8 s = src[i];
- uint8& d = m_byte[i];
- d = ((int)s.r + (int)s.g + (int)s.b) / 3;
- }
- m_memMan->free(src);
- }
- break;
-
- case 4:
- {
- // Average
- Color4uint8* src = (Color4uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 1);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color4uint8 s = src[i];
- uint8& d = m_byte[i];
- d = ((int)s.r + (int)s.g + (int)s.b) / 3;
- }
- m_memMan->free(src);
- }
- return;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::convertToRGBA() {
- switch (m_channels) {
- case 1:
- {
- // Spread
- uint8* old = m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 4);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const uint8 s = old[i];
- Color4uint8& d = ((Color4uint8*)m_byte)[i];
- d.r = d.g = d.b = s;
- d.a = 255;
- }
- m_memMan->free(m_byte);
- }
- break;
-
- case 3:
- {
- // Add alpha
- Color3uint8* old = (Color3uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 4);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color3uint8 s = old[i];
- Color4uint8& d = ((Color4uint8*)m_byte)[i];
- d.r = s.r;
- d.g = s.g;
- d.b = s.b;
- d.a = 255;
- }
- m_memMan->free(old);
- }
- break;
-
- case 4:
- // Already RGBA
- return;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::convertToRGB() {
- switch (m_channels) {
- case 1:
- {
- // Spread
- uint8* old = m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 3);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const uint8 s = old[i];
- Color3uint8& d = ((Color3uint8*)m_byte)[i];
- d.r = d.g = d.b = s;
- }
- m_memMan->free(old);
- }
- break;
-
- case 3:
- return;
-
- case 4:
- // Strip alpha
- {
- Color4uint8* old = (Color4uint8*)m_byte;
- m_byte = NULL;
- resize(m_width, m_height, 3);
- for (int i = m_width * m_height - 1; i >= 0; --i) {
- const Color4uint8 s = old[i];
- Color3uint8& d = ((Color3uint8*)m_byte)[i];
- d.r = s.r;
- d.g = s.g;
- d.b = s.b;
- }
- m_memMan->free(old);
- }
- break;
-
- default:
- alwaysAssertM(false, "Bad number of channels in input image");
- }
-}
-
-
-void GImage::R8G8B8_to_Y8U8V8(int width, int height, const uint8* _in, uint8* _out) {
- const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in);
- Color3uint8* out = reinterpret_cast<Color3uint8*>(_out);
-
- Color3uint8 p;
- for (int i = width * height - 1; i >= 0; --i) {
- p.r = iClamp(iRound(in->r * 0.229 + in->g * 0.587 + in->b * 0.114), 0, 255);
- p.g = iClamp(iRound(in->r * -0.147 + in->g * -0.289 + in->b * 0.436) + 127, 0, 255);
- p.b = iClamp(iRound(in->r * 0.615 + in->g * -0.515 + in->b * -0.100) + 127, 0, 255);
- *out = p;
- ++in;
- ++out;
- }
-}
-
-
-
-void GImage::Y8U8V8_to_R8G8B8(int width, int height, const uint8* _in, uint8* _out) {
- const Color3uint8* in = reinterpret_cast<const Color3uint8*>(_in);
- Color3uint8* out = reinterpret_cast<Color3uint8*>(_out);
-
- Color3uint8 p;
- for (int i = width * height - 1; i >= 0; --i) {
- p.r = iClamp(iRound(in->r * 1.0753 + (in->b - 127) * 1.2256), 0, 255);
- p.g = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * -0.3946 + (in->b - 127) * -0.4947), 0, 255);
- p.b = iClamp(iRound(in->r * 1.0753 + (in->g - 127) * 2.0320 + (in->b - 127) * 0.0853), 0, 255);
- *out = p;
- ++in;
- ++out;
- }
-}
-
-
-void GImage::makeCheckerboard(GImage& im, int checkerSize, const Color4uint8& A, const Color4uint8& B) {
- for (int y = 0; y < im.m_height; ++y) {
- for (int x = 0; x < im.m_width; ++x) {
- bool checker = isOdd((x / checkerSize) + (y / checkerSize));
- const Color4uint8& color = checker ? A : B;
- for (int c = 0; c < im.m_channels; ++c) {
- uint8* v = im.byte() + (x + y * im.m_width) * im.m_channels + c;
- *v = color[c];
- }
- }
- }
-}
-
-}
-
diff --git a/dep/g3dlite/source/GImage_bayer.cpp b/dep/g3dlite/source/GImage_bayer.cpp
deleted file mode 100644
index 3d08e8ade5f..00000000000
--- a/dep/g3dlite/source/GImage_bayer.cpp
+++ /dev/null
@@ -1,298 +0,0 @@
-/**
- @file GImage_bayer.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-
-namespace G3D {
-
-void GImage::BAYER_G8B8_R8G8_to_Quarter_R8G8B8(int width, int height, const uint8* in, uint8* out) {
- debugAssert(in != out);
-
- int halfHeight = height / 2;
- int halfWidth = width / 2;
-
- int dst_off = 0;
- for (int y = 0; y < halfHeight; ++y) {
- for (int x = 0; x < halfWidth; ++x) {
- // GBRG
- int src_off = x*2 + y*2*width;
- out[dst_off] = in[src_off+width]; // red
- out[dst_off+1] = ((int)in[src_off] + (int)in[src_off+width+1])/2; // green
- out[dst_off+2] = in[src_off+1]; // blue
-
- dst_off = dst_off + 3;
- }
- }
-}
-
-
-void GImage::Quarter_R8G8B8_to_BAYER_G8B8_R8G8(int inWidth, int inHeight, const uint8* in, uint8* out) {
- // Undo quarter-size Bayer as best we can. This code isn't very efficient, but it
- // also isn't used very frequently.
-
- debugAssert(out != in);
-
- int outWidth = 2 * inWidth;
- int outHeight = 2 * inHeight;
-
- for (int y = 0; y < outHeight; ++y) {
- for (int x = 0; x < outWidth; ++x) {
- const Color3uint8* inp = ((const Color3uint8*)in) + ((x/2) + (y/2)* inWidth);
- uint8* outp = out + x + y * outWidth;
-
- if (isEven(y)) {
- // GB row
- if (isEven(x)) {
- // Green
- *outp = inp->g;
- } else {
- // Blue
- *outp = inp->b;
- }
- } else {
- // RG row
- if (isEven(x)) {
- // Red
- *outp = inp->r;
- } else {
- // Green
- *outp = inp->g;
- }
- }
- }
- }
-}
-
-
-/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */
-static uint8 applyFilter(
- const uint8* I,
- int x,
- int y,
- int w,
- int h,
- const float filter[5][5]) {
-
- debugAssert(isEven(w));
- debugAssert(isEven(h));
-
- float sum = 0.0f;
- float denom = 0.0f;
-
- for (int dy = 0; dy < 5; ++dy) {
- int offset = ((y + dy + h - 2) % h) * w;
-
- for (int dx = 0; dx < 5; ++dx) {
- float f = filter[dy][dx];
- sum += f * I[((x + dx + w - 2) % w) + offset];
- denom += f;
- }
- }
-
- return (uint8)iClamp(iRound(sum / denom), 0, 255);
-}
-
-////////////////////////////////////////////////////////////////////////////////////////////////
-//
-// Bayer conversions
-//
-
-// There are two kinds of rows (GR and BG).
-// In each row, there are two kinds of pixels (G/R, B/G).
-// We express the four kinds of INPUT pixels as:
-// GRG, GRG, BGB, BGG
-//
-// There are three kinds of OUTPUT pixels: R, G, B.
-// Thus there are nominally 12 different I/O combinations,
-// but several are impulses because needed output at that
-// location *is* the input (e.g., G_GRG and G_BGG).
-//
-// The following 5x5 row-major filters are named as output_input.
-
-// Green
-static const float G_GRR[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-static const float G_BGB[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ -1.0f, 2.0f, 4.0f, 2.0f, -1.0f},
-{ 0.0f, 0.0f, 2.0f, 0.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-// Red
-//(the caption in the paper is wrong for this case:
-// "R row B column really means R row G column"
-static const float R_GRG[5][5] =
-{{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f},
-{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
-{ -1.0f, 4.0f, 5.0f, 4.0f, -1.0f},
-{ 0.0f, -1.0f, 0.0f, -1.0f, 0.0f},
-{ 0.0f, 0.0f, 0.5f, 0.0f, 0.0f}};
-
-static const float R_BGG[5][5] =
-{{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f},
-{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
-{ 0.5f, 0.0f, 5.0f, 0.0f, 0.5f},
-{ 0.0f, -1.0f, 4.0f, -1.0f, 0.0f},
-{ 0.0f, 0.0f, -1.0f, 0.0f, 0.0f}};
-
-static const float R_BGB[5][5] =
-{{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f},
-{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
-{-3.0f/2.0f, 0.0f, 6.0f, 0.0f, -3.0f/2.0f},
-{ 0.0f, 2.0f, 0.0f, 2.0f, 0.0f},
-{ 0.0f, 0.0f, -3.0f/2.0f, 0.0f, 0.0f}};
-
-
-// Blue
-//(the caption in the paper is wrong for this case:
-// "B row R column really means B row G column")
-#define B_BGG R_GRG
-#define B_GRG R_BGG
-#define B_GRR R_BGB
-
-
-void GImage::BAYER_R8G8_G8B8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- debugAssert(in != _out);
-
- Color3uint8* out = (Color3uint8*)_out;
-
- for (int y = 0; y < h; ++y) {
-
- // Row beginning in the input array.
- int offset = y * w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
-
- ++y;
- offset += w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
- }
-}
-
-static void swapRedAndBlue(int N, Color3uint8* out) {
- for (int i = N - 1; i >= 0; --i) {
- uint8 tmp = out[i].r;
- out[i].r = out[i].b;
- out[i].b = tmp;
- }
-}
-
-void GImage::BAYER_G8R8_B8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- // Run the equivalent function for red
- BAYER_G8B8_R8G8_to_R8G8B8_MHC(w, h, in, _out);
-
- // Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
-}
-
-
-void GImage::BAYER_B8G8_G8R8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
- // Run the equivalent function for red
- BAYER_R8G8_G8B8_to_R8G8B8_MHC(w, h, in, _out);
-
- // Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
-}
-
-
-void GImage::BAYER_G8B8_R8G8_to_R8G8B8_MHC(int w, int h, const uint8* in, uint8* _out) {
-
- debugAssert(in != _out);
-
- Color3uint8* out = (Color3uint8*)_out;
-
- for (int y = 0; y < h; ++y) {
-
- // Row beginning in the input array.
- int offset = y * w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
-
- ++y;
- offset += w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
- }
-
-}
-
-#undef B_BGG
-#undef B_GRG
-#undef B_GRR
-
-}
diff --git a/dep/g3dlite/source/GImage_bmp.cpp b/dep/g3dlite/source/GImage_bmp.cpp
deleted file mode 100644
index 425a7e1a1d2..00000000000
--- a/dep/g3dlite/source/GImage_bmp.cpp
+++ /dev/null
@@ -1,717 +0,0 @@
-/**
- @file GImage_bmp.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-#ifndef G3D_WIN32
-/**
- This is used by the Windows bitmap I/O.
- */
-static const int BI_RGB = 0;
-#endif
-
-void GImage::encodeBMP(
- BinaryOutput& out) const {
-
- debugAssert(m_channels == 1 || m_channels == 3);
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- uint8 red;
- uint8 green;
- uint8 blue;
- int pixelBufferSize = m_width * m_height * 3;
- int fileHeaderSize = 14;
- int infoHeaderSize = 40;
- int BMScanWidth;
- int BMPadding;
-
- // First write the BITMAPFILEHEADER
- //
- // WORD bfType;
- // DWORD bfSize;
- // WORD bfReserved1;
- // WORD bfReserved2;
- // DWORD bfOffBits;
-
- // Type
- out.writeUInt8('B');
- out.writeUInt8('M');
-
- // File size
- out.writeUInt32(fileHeaderSize + infoHeaderSize + pixelBufferSize);
-
- // Two reserved fields set to zero
- out.writeUInt16(0);
- out.writeUInt16(0);
-
- // The offset, in bytes, from the BITMAPFILEHEADER structure
- // to the bitmap bits.
- out.writeUInt32(infoHeaderSize + fileHeaderSize);
-
- // Now the BITMAPINFOHEADER
- //
- // DWORD biSize;
- // LONG biWidth;
- // LONG biHeight;
- // WORD biPlanes;
- // WORD biBitCount
- // DWORD biCompression;
- // DWORD biSizeImage;
- // LONG biXPelsPerMeter;
- // LONG biYPelsPerMeter;
- // DWORD biClrUsed;
- // DWORD biClrImportant;
-
- // Size of the info header
- out.writeUInt32(infoHeaderSize);
-
- // Width and height of the image
- out.writeUInt32(m_width);
- out.writeUInt32(m_height);
-
- // Planes ("must be set to 1")
- out.writeUInt16(1);
-
- // BitCount and CompressionType
- out.writeUInt16(24);
- out.writeUInt32(BI_RGB);
-
- // Image size ("may be zero for BI_RGB bitmaps")
- out.writeUInt32(0);
-
- // biXPelsPerMeter
- out.writeUInt32(0);
- // biYPelsPerMeter
- out.writeUInt32(0);
-
- // biClrUsed
- out.writeUInt32(0);
-
- // biClrImportant
- out.writeUInt32(0);
-
- BMScanWidth = m_width * 3;
-
- if (BMScanWidth & 3) {
- BMPadding = 4 - (BMScanWidth & 3);
- } else {
- BMPadding = 0;
- }
-
- int hStart = m_height - 1;
- int hEnd = -1;
- int hDir = -1;
- int dest;
-
- // Write the pixel data
- for (int h = hStart; h != hEnd; h += hDir) {
- dest = m_channels * h * m_width;
- for (int w = 0; w < m_width; ++w) {
-
- if (m_channels == 3) {
- red = m_byte[dest];
- green = m_byte[dest + 1];
- blue = m_byte[dest + 2];
- } else {
- red = m_byte[dest];
- green = m_byte[dest];
- blue = m_byte[dest];
- }
-
- out.writeUInt8(blue);
- out.writeUInt8(green);
- out.writeUInt8(red);
-
- dest += m_channels;
- }
-
- if (BMPadding > 0) {
- out.skip(BMPadding);
- }
- }
-}
-
-
-void GImage::decodeBMP(
- BinaryInput& input) {
-
- // The BMP decoding uses these flags.
- static const uint16 PICTURE_NONE = 0x0000;
- static const uint16 PICTURE_BITMAP = 0x1000;
-
- // Compression Flags
- static const uint16 PICTURE_UNCOMPRESSED = 0x0100;
- static const uint16 PICTURE_MONOCHROME = 0x0001;
- static const uint16 PICTURE_4BIT = 0x0002;
- static const uint16 PICTURE_8BIT = 0x0004;
- static const uint16 PICTURE_16BIT = 0x0008;
- static const uint16 PICTURE_24BIT = 0x0010;
- static const uint16 PICTURE_32BIT = 0x0020;
-
- (void)PICTURE_16BIT;
- (void)PICTURE_32BIT;
-
- // This is a simple BMP loader that can handle uncompressed BMP files.
- // Verify this is a BMP file by looking for the BM tag.
- input.reset();
- std::string tag = input.readString(2);
- if (tag != "BM") {
- throw Error("Not a BMP file", input.getFilename());
- }
-
- m_channels = 3;
- // Skip to the BITMAPINFOHEADER's width and height
- input.skip(16);
-
- m_width = input.readUInt32();
- m_height = input.readUInt32();
-
- // Skip to the bit count and compression type
- input.skip(2);
-
- uint16 bitCount = input.readUInt16();
- uint32 compressionType = input.readUInt32();
-
- uint8 red;
- uint8 green;
- uint8 blue;
- uint8 blank;
-
- // Only uncompressed bitmaps are supported by this code
- if ((int32)compressionType != BI_RGB) {
- throw Error("BMP images must be uncompressed", input.getFilename());
- }
-
- uint8* palette = NULL;
-
- // Create the palette if needed
- if (bitCount <= 8) {
-
- // Skip to the palette color count in the header
- input.skip(12);
-
- int numColors = input.readUInt32();
-
- palette = (uint8*)System::malloc(numColors * 3);
- debugAssert(palette);
-
- // Skip past the end of the header to the palette info
- input.skip(4);
-
- int c;
- for(c = 0; c < numColors * 3; c += 3) {
- // Palette information in bitmaps is stored in BGR_ format.
- // That means it's blue-green-red-blank, for each entry.
- blue = input.readUInt8();
- green = input.readUInt8();
- red = input.readUInt8();
- blank = input.readUInt8();
-
- palette[c] = red;
- palette[c + 1] = green;
- palette[c + 2] = blue;
- }
- }
-
- int hStart = 0;
- int hEnd = 0;
- int hDir = 0;
-
- if (m_height < 0) {
- m_height = -m_height;
- hStart = 0;
- hEnd = m_height;
- hDir = 1;
- } else {
- //height = height;
- hStart = m_height - 1;
- hEnd = -1;
- hDir = -1;
- }
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
- debugAssert(m_byte);
-
- int BMScanWidth;
- int BMPadding;
- uint8 BMGroup;
- uint8 BMPixel8;
- int currPixel;
- int dest;
- int flags = PICTURE_NONE;
-
- if (bitCount == 1) {
- // Note that this file is not necessarily grayscale, since it's possible
- // the palette is blue-and-white, or whatever. But of course most image
- // programs only write 1-bit images if they're black-and-white.
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_MONOCHROME;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = (m_width + 7) >> 3;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- // Powers of 2
- int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMGroup = input.readUInt8();
-
- // Now we read the pixels. Usually there are eight pixels per byte,
- // since each pixel is represented by one bit, but if the width
- // is not a multiple of eight, the last byte will have some bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "width" number of pixels.
- for (int i = 7; i >= 0; --i) {
- if (currPixel < m_width) {
- int src = 3 * ((BMGroup & pow2[i]) >> i);
-
- m_byte[dest] = palette[src];
- m_byte[dest + 1] = palette[src + 1];
- m_byte[dest + 2] = palette[src + 2];
-
- ++currPixel;
- dest += 3;
- }
- }
- }
- }
-
- } else if (bitCount == 4) {
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_4BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- int BMScanWidth = (m_width + 1) >> 1;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; w++) {
-
- BMGroup = input.readUInt8();
- int src[2];
- src[0] = 3 * ((BMGroup & 0xF0) >> 4);
- src[1] = 3 * (BMGroup & 0x0F);
-
- // Now we read the pixels. Usually there are two pixels per byte,
- // since each pixel is represented by four bits, but if the width
- // is not a multiple of two, the last byte will have only four bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "Width" number of pixels.
-
- for (int i = 0; i < 2; ++i) {
- if (currPixel < m_width) {
- int tsrc = src[i];
-
- m_byte[dest] = palette[tsrc];
- m_byte[dest + 1] = palette[tsrc + 1];
- m_byte[dest + 2] = palette[tsrc + 2];
-
- ++currPixel;
- dest += 3;
- }
- }
- }
- }
-
- } else if (bitCount == 8) {
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_8BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMPixel8 = input.readUInt8();
-
- if (currPixel < m_width) {
- dest = 3 * ((h * m_width) + currPixel);
- int src = 3 * BMPixel8;
-
- m_byte[dest] = palette[src];
- m_byte[dest + 1] = palette[src + 1];
- m_byte[dest + 2] = palette[src + 2];
-
- ++currPixel;
- }
- }
- }
-
- } else if (bitCount == 16) {
-
- m_memMan->free(m_byte);
- m_byte = NULL;
- System::free(palette);
- palette = NULL;
- throw Error("16-bit bitmaps not supported", input.getFilename());
-
- } else if (bitCount == 24) {
- input.skip(20);
-
- flags = PICTURE_BITMAP | PICTURE_UNCOMPRESSED | PICTURE_24BIT;
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width * 3;
-
- if (BMScanWidth & 3) {
- BMPadding = 4 - (BMScanWidth & 3);
- } else {
- BMPadding = 0;
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
- dest = 3 * h * m_width;
- for (int w = 0; w < m_width; ++w) {
-
- blue = input.readUInt8();
- green = input.readUInt8();
- red = input.readUInt8();
-
- m_byte[dest] = red;
- m_byte[dest + 1] = green;
- m_byte[dest + 2] = blue;
-
- dest += 3;
- }
-
- if (BMPadding) {
- input.skip(2);
- }
- }
-
- } else if (bitCount == 32) {
-
- m_memMan->free(m_byte);
- m_byte = NULL;
- System::free(palette);
- palette = NULL;
- throw Error("32 bit bitmaps not supported", input.getFilename());
-
- } else {
- // We support all possible bit depths, so if the
- // code gets here, it's not even a real bitmap.
- m_memMan->free(m_byte);
- m_byte = NULL;
- throw Error("Not a bitmap!", input.getFilename());
- }
-
- System::free(palette);
- palette = NULL;
-}
-
-
-void GImage::decodeICO(
- BinaryInput& input) {
-
- // Header
- uint16 r = input.readUInt16();
- debugAssert(r == 0);
- r = input.readUInt16();
- debugAssert(r == 1);
-
- // Read the number of icons, although we'll only load the
- // first one.
- int count = input.readUInt16();
-
- m_channels = 4;
-
- debugAssert(count > 0);
-
- const uint8* headerBuffer = input.getCArray() + input.getPosition();
- int maxWidth = 0, maxHeight = 0;
- int maxHeaderNum = 0;
- for (int currentHeader = 0; currentHeader < count; ++currentHeader) {
-
- const uint8* curHeaderBuffer = headerBuffer + (currentHeader * 16);
- int tmpWidth = curHeaderBuffer[0];
- int tmpHeight = curHeaderBuffer[1];
- // Just in case there is a non-square icon, checking area
- if ((tmpWidth * tmpHeight) > (maxWidth * maxHeight)) {
- maxWidth = tmpWidth;
- maxHeight = tmpHeight;
- maxHeaderNum = currentHeader;
- }
- }
-
- input.skip(maxHeaderNum * 16);
-
- m_width = input.readUInt8();
- m_height = input.readUInt8();
- int numColors = input.readUInt8();
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- debugAssert(m_byte);
-
- // Bit mask for packed bits
- int mask = 0;
-
- int bitsPerPixel = 8;
-
- switch (numColors) {
- case 2:
- mask = 0x01;
- bitsPerPixel = 1;
- break;
-
- case 16:
- mask = 0x0F;
- bitsPerPixel = 4;
- break;
-
- case 0:
- numColors = 256;
- mask = 0xFF;
- bitsPerPixel = 8;
- break;
-
- default:
- throw Error("Unsupported ICO color count.", input.getFilename());
- }
-
- input.skip(5);
- // Skip 'size' unused
- input.skip(4);
-
- int offset = input.readUInt32();
-
- // Skip over any other icon descriptions
- input.setPosition(offset);
-
- // Skip over bitmap header; it is redundant
- input.skip(40);
-
- Array<Color4uint8> palette;
- palette.resize(numColors, true);
- for (int c = 0; c < numColors; ++c) {
- palette[c].b = input.readUInt8();
- palette[c].g = input.readUInt8();
- palette[c].r = input.readUInt8();
- palette[c].a = input.readUInt8();
- }
-
- // The actual image and mask follow
-
- // The XOR Bitmap is stored as 1-bit, 4-bit or 8-bit uncompressed Bitmap
- // using the same encoding as BMP files. The AND Bitmap is stored in as
- // 1-bit uncompressed Bitmap.
- //
- // Pixels are stored bottom-up, left-to-right. Pixel lines are padded
- // with zeros to end on a 32bit (4byte) boundary. Every line will have the
- // same number of bytes. Color indices are zero based, meaning a pixel color
- // of 0 represents the first color table entry, a pixel color of 255 (if there
- // are that many) represents the 256th entry.
-/*
- int bitsPerRow = width * bitsPerPixel;
- int bytesPerRow = iCeil((double)bitsPerRow / 8);
- // Rows are padded to 32-bit boundaries
- bytesPerRow += bytesPerRow % 4;
-
- // Read the XOR values into the color channel
- for (int y = height - 1; y >= 0; --y) {
- int x = 0;
- // Read the row
- for (int i = 0; i < bytesPerRow; ++i) {
- uint8 byte = input.readUInt8();
- for (int j = 0; (j < 8) && (x < width); ++x, j += bitsPerPixel) {
- int bit = ((byte << j) >> (8 - bitsPerPixel)) & mask;
- pixel4(x, y) = colorTable[bit];
- }
- }
- }
-*/
- int hStart = 0;
- int hEnd = 0;
- int hDir = 0;
-
- if (m_height < 0) {
- m_height = -m_height;
- hStart = 0;
- hEnd = m_height;
- hDir = 1;
- } else {
- //height = height;
- hStart = m_height - 1;
- hEnd = -1;
- hDir = -1;
- }
-
- int BMScanWidth;
- uint8 BMGroup;
- uint8 BMPixel8;
- int currPixel;
- int dest;
-
- if (bitsPerPixel == 1) {
- // Note that this file is not necessarily grayscale, since it's possible
- // the palette is blue-and-white, or whatever. But of course most image
- // programs only write 1-bit images if they're black-and-white.
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = (m_width + 7) >> 3;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- // Powers of 2
- int pow2[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80};
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 3 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMGroup = input.readUInt8();
-
- // Now we read the pixels. Usually there are eight pixels per byte,
- // since each pixel is represented by one bit, but if the width
- // is not a multiple of eight, the last byte will have some bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "width" number of pixels.
- for (int i = 7; i >= 0; --i) {
- if (currPixel < m_width) {
- int src = ((BMGroup & pow2[i]) >> i);
-
- m_byte[dest] = palette[src].r;
- m_byte[dest + 1] = palette[src].g;
- m_byte[dest + 2] = palette[src].b;
-
- ++currPixel;
- dest += 4;
- }
- }
- }
- }
-
- } else if (bitsPerPixel == 4) {
-
- // For bitmaps, each scanline is dword-aligned.
- int BMScanWidth = (m_width + 1) >> 1;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
- dest = 4 * h * m_width;
-
- for (int w = 0; w < BMScanWidth; w++) {
-
- BMGroup = input.readUInt8();
- int src[2];
- src[0] = ((BMGroup & 0xF0) >> 4);
- src[1] = (BMGroup & 0x0F);
-
- // Now we read the pixels. Usually there are two pixels per byte,
- // since each pixel is represented by four bits, but if the width
- // is not a multiple of two, the last byte will have only four bits
- // set, with the others just being extra. Plus there's the
- // dword-alignment padding. So we keep checking to see if we've
- // already read "Width" number of pixels.
-
- for (int i = 0; i < 2; ++i) {
- if (currPixel < m_width) {
- int tsrc = src[i];
-
- m_byte[dest] = palette[tsrc].r;
- m_byte[dest + 1] = palette[tsrc].g;
- m_byte[dest + 2] = palette[tsrc].b;
-
- ++currPixel;
- dest += 4;
- }
- }
- }
- }
-
- } else if (bitsPerPixel == 8) {
-
- // For bitmaps, each scanline is dword-aligned.
- BMScanWidth = m_width;
- if (BMScanWidth & 3) {
- BMScanWidth += 4 - (BMScanWidth & 3);
- }
-
- for (int h = hStart; h != hEnd; h += hDir) {
-
- currPixel = 0;
-
- for (int w = 0; w < BMScanWidth; ++w) {
-
- BMPixel8 = input.readUInt8();
-
- if (currPixel < m_width) {
- dest = 4 * ((h * m_width) + currPixel);
- int src = BMPixel8;
-
- m_byte[dest] = palette[src].r;
- m_byte[dest + 1] = palette[src].g;
- m_byte[dest + 2] = palette[src].b;
-
- ++currPixel;
- }
- }
- }
- }
-
- // Read the mask into the alpha channel
- int bitsPerRow = m_width;
- int bytesPerRow = iCeil((double)bitsPerRow / 8);
-
- // For bitmaps, each scanline is dword-aligned.
- //BMScanWidth = (width + 1) >> 1;
- if (bytesPerRow & 3) {
- bytesPerRow += 4 - (bytesPerRow & 3);
- }
-
- for (int y = m_height - 1; y >= 0; --y) {
- int x = 0;
- // Read the row
- for (int i = 0; i < bytesPerRow; ++i) {
- uint8 byte = input.readUInt8();
- for (int j = 0; (j < 8) && (x < m_width); ++x, ++j) {
- int bit = (byte >> (7 - j)) & 0x01;
- pixel4(x, y).a = (1 - bit) * 0xFF;
- }
- }
- }
-
-}
-
-
-}
diff --git a/dep/g3dlite/source/GImage_jpeg.cpp b/dep/g3dlite/source/GImage_jpeg.cpp
deleted file mode 100644
index 0b0521f31e7..00000000000
--- a/dep/g3dlite/source/GImage_jpeg.cpp
+++ /dev/null
@@ -1,446 +0,0 @@
-/**
- @file GImage_jpeg.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-04-20
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-
-#include <cstring>
-
-extern "C" {
-#ifdef G3D_LINUX
-# include <jconfig.h>
-# include <jpeglib.h>
-#else
-# include "jconfig.h"
-# include "jpeglib.h"
-#endif
-}
-
-namespace G3D {
-
-
-const int jpegQuality = 96;
-
-/**
- The IJG library needs special setup for compress/decompressing
- from memory. These classes provide them.
-
- The format of this class is defined by the IJG library; do not
- change it.
- */
-class memory_destination_mgr {
-public:
- struct jpeg_destination_mgr pub;
- JOCTET* buffer;
- int size;
- int count;
-};
-
-typedef memory_destination_mgr* mem_dest_ptr;
-
-/**
- Signature dictated by IJG.
- */
-static void init_destination (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
-
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = dest->size;
- dest->count=0;
-}
-
-/**
- Signature dictated by IJG.
- */
-static boolean empty_output_buffer (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
-
- dest->pub.next_output_byte = dest->buffer;
- dest->pub.free_in_buffer = dest->size;
-
- return TRUE;
-}
-
-/**
- Signature dictated by IJG.
- */
-static void term_destination (
- j_compress_ptr cinfo) {
-
- mem_dest_ptr dest = (mem_dest_ptr) cinfo->dest;
- dest->count = dest->size - dest->pub.free_in_buffer;
-}
-
-/**
- Signature dictated by IJG.
- */
-static void jpeg_memory_dest (
- j_compress_ptr cinfo,
- JOCTET* buffer,
- int size) {
-
- mem_dest_ptr dest;
-
- if (cinfo->dest == NULL) {
- // First time for this JPEG object; call the
- // IJG allocator to get space.
- cinfo->dest = (struct jpeg_destination_mgr*)
- (*cinfo->mem->alloc_small) ((j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- sizeof(memory_destination_mgr));
- }
-
- dest = (mem_dest_ptr) cinfo->dest;
- dest->size = size;
- dest->buffer = buffer;
- dest->pub.init_destination = init_destination;
- dest->pub.empty_output_buffer = empty_output_buffer;
- dest->pub.term_destination = term_destination;
-}
-
-////////////////////////////////////////////////////////////////////////////////////////
-
-#define INPUT_BUF_SIZE 4096
-
-/**
- Structure dictated by IJG.
- */
-class memory_source_mgr {
-public:
- struct jpeg_source_mgr pub;
- int source_size;
- unsigned char* source_data;
- boolean start_of_data;
- JOCTET* buffer;
-};
-
-
-typedef memory_source_mgr* mem_src_ptr;
-
-
-/**
- Signature dictated by IJG.
- */
-static void init_source(
- j_decompress_ptr cinfo) {
-
- mem_src_ptr src = (mem_src_ptr) cinfo->src;
-
- src->start_of_data = TRUE;
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static boolean fill_input_buffer(
- j_decompress_ptr cinfo) {
-
- mem_src_ptr src = (mem_src_ptr) cinfo->src;
-
- size_t bytes_read = 0;
-
- if (src->source_size > INPUT_BUF_SIZE)
- bytes_read = INPUT_BUF_SIZE;
- else
- bytes_read = src->source_size;
-
- memcpy (src->buffer, src->source_data, bytes_read);
-
- src->source_data += bytes_read;
- src->source_size -= bytes_read;
-
- src->pub.next_input_byte = src->buffer;
- src->pub.bytes_in_buffer = bytes_read;
- src->start_of_data = FALSE;
-
-
- return TRUE;
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void skip_input_data(
- j_decompress_ptr cinfo,
- long num_bytes) {
-
- mem_src_ptr src = (mem_src_ptr)cinfo->src;
-
- if (num_bytes > 0) {
- while (num_bytes > (long) src->pub.bytes_in_buffer) {
- num_bytes -= (long) src->pub.bytes_in_buffer;
- boolean s = fill_input_buffer(cinfo);
- debugAssert(s); (void)s;
- }
-
- src->pub.next_input_byte += (size_t) num_bytes;
- src->pub.bytes_in_buffer -= (size_t) num_bytes;
- }
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void term_source (
- j_decompress_ptr cinfo) {
- (void)cinfo;
- // Intentionally empty
-}
-
-
-/**
- Signature dictated by IJG.
- */
-static void jpeg_memory_src (
- j_decompress_ptr cinfo,
- JOCTET* buffer,
- int size) {
-
- mem_src_ptr src;
-
- if (cinfo->src == NULL) {
- // First time for this JPEG object
- cinfo->src = (struct jpeg_source_mgr*)
- (*cinfo->mem->alloc_small)(
- (j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- sizeof(memory_source_mgr));
-
- src = (mem_src_ptr)cinfo->src;
-
- src->buffer = (JOCTET*)
- (*cinfo->mem->alloc_small)(
- (j_common_ptr) cinfo,
- JPOOL_PERMANENT,
- INPUT_BUF_SIZE * sizeof(JOCTET));
- }
-
- src = (mem_src_ptr)cinfo->src;
- src->pub.init_source = init_source;
- src->pub.fill_input_buffer = fill_input_buffer;
- src->pub.skip_input_data = skip_input_data;
-
- // use default method
- src->pub.resync_to_restart = jpeg_resync_to_restart;
- src->pub.term_source = term_source;
- src->source_data = buffer;
- src->source_size = size;
-
- // forces fill_input_buffer on first read
- src->pub.bytes_in_buffer = 0;
-
- // until buffer loaded
- src->pub.next_input_byte = NULL;
-}
-
-
-void GImage::encodeJPEG(
- BinaryOutput& out) const {
-
- if (m_channels != 3) {
- // Convert to three channel
- GImage tmp = *this;
- tmp.convertToRGB();
- tmp.encodeJPEG(out);
- return;
- }
-
- debugAssert(m_channels == 3);
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- // Allocate and initialize a compression object
- jpeg_compress_struct cinfo;
- jpeg_error_mgr jerr;
-
- cinfo.err = jpeg_std_error(&jerr);
- jpeg_create_compress(&cinfo);
-
- // Specify the destination for the compressed data.
- // (Overestimate the size)
- int buffer_size = m_width * m_height * 3 + 200;
- JOCTET* compressed_data = (JOCTET*)System::malloc(buffer_size);
- jpeg_memory_dest(&cinfo, compressed_data, buffer_size);
-
-
- cinfo.image_width = m_width;
- cinfo.image_height = m_height;
-
- // # of color components per pixel
- cinfo.input_components = 3;
-
- // colorspace of input image
- cinfo.in_color_space = JCS_RGB;
- cinfo.input_gamma = 1.0;
-
- // Set parameters for compression, including image size & colorspace
- jpeg_set_defaults(&cinfo);
- jpeg_set_quality(&cinfo, jpegQuality, false);
- cinfo.smoothing_factor = 0;
- cinfo.optimize_coding = TRUE;
-// cinfo.dct_method = JDCT_FLOAT;
- cinfo.dct_method = JDCT_ISLOW;
- cinfo.jpeg_color_space = JCS_YCbCr;
-
- // Initialize the compressor
- jpeg_start_compress(&cinfo, TRUE);
-
- // Iterate over all scanlines from top to bottom
- // pointer to a single row
- JSAMPROW row_pointer[1];
-
- // JSAMPLEs per row in image_buffer
- int row_stride = cinfo.image_width * 3;
- while (cinfo.next_scanline < cinfo.image_height) {
- row_pointer[0] = &(m_byte[cinfo.next_scanline * row_stride]);
- jpeg_write_scanlines(&cinfo, row_pointer, 1);
- }
-
- // Shut down the compressor
- jpeg_finish_compress(&cinfo);
-
- // Figure out how big the result was.
- int outLength = ((mem_dest_ptr)cinfo.dest)->count;
-
- // Release the JPEG compression object
- jpeg_destroy_compress(&cinfo);
-
- // Copy into an appropriately sized output buffer.
- out.writeBytes(compressed_data, outLength);
-
- // Free the conservative buffer.
- System::free(compressed_data);
- compressed_data = NULL;
-}
-
-
-void GImage::decodeJPEG(
- BinaryInput& input) {
-
- struct jpeg_decompress_struct cinfo;
- struct jpeg_error_mgr jerr;
- int loc = 0;
-
- m_channels = 3;
- // We have to set up the error handler, in case initialization fails.
- cinfo.err = jpeg_std_error(&jerr);
-
- // Initialize the JPEG decompression object.
- jpeg_create_decompress(&cinfo);
-
- // Specify data source (eg, a file, for us, memory)
- jpeg_memory_src(&cinfo, const_cast<uint8*>(input.getCArray()), input.size());
-
- // Read the parameters with jpeg_read_header()
- jpeg_read_header(&cinfo, TRUE);
-
- // Set parameters for decompression
- // (We do nothing here since the defaults are fine)
-
- // Start decompressor
- jpeg_start_decompress(&cinfo);
-
- // Get and set the values of interest to this object
- m_width = cinfo.output_width;
- m_height = cinfo.output_height;
-
- // Prepare the pointer object for the pixel data
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- // JSAMPLEs per row in output buffer
- int bpp = cinfo.output_components;
- int row_stride = cinfo.output_width * bpp;
-
- // Make a one-row-high sample array that will go away when done with image
- JSAMPARRAY temp = (*cinfo.mem->alloc_sarray)
- ((j_common_ptr) &cinfo, JPOOL_IMAGE, row_stride, 1);
-
- // Read data on a scanline by scanline basis
- while (cinfo.output_scanline < cinfo.output_height) {
-
- // We may need to adjust the output based on the
- // number of channels it has.
- switch (bpp) {
- case 1:
- // Grayscale; decompress to temp.
- jpeg_read_scanlines(&cinfo, temp, 1);
-
- // Expand to three channels
- {
- uint8* scan = &(m_byte[loc * 3]);
- uint8* endScan = scan + (m_width * 3);
- uint8* t = *temp;
-
- while (scan < endScan) {
- uint8 value = t[0];
-
- // Spread the value 3x.
- scan[0] = value;
- scan[1] = value;
- scan[2] = value;
-
- scan += 3;
- t += 1;
- }
- }
- break;
-
- case 3:
- // Read directly into the array
- {
- // Need one extra level of indirection.
- uint8* scan = m_byte + loc;
- JSAMPARRAY ptr = &scan;
- jpeg_read_scanlines(&cinfo, ptr, 1);
- }
- break;
-
- case 4:
- // RGBA; decompress to temp.
- jpeg_read_scanlines(&cinfo, temp, 1);
-
- // Drop the 3rd channel
- {
- uint8* scan = &(m_byte[loc * 3]);
- uint8* endScan = scan + m_width * 3;
- uint8* t = *temp;
-
- while (scan < endScan) {
- scan[0] = t[0];
- scan[1] = t[1];
- scan[2] = t[2];
-
- scan += 3;
- t += 4;
- }
- }
- break;
-
- default:
- throw Error("Unexpected number of channels.", input.getFilename());
- }
-
- loc += row_stride;
- }
-
- // Finish decompression
- jpeg_finish_decompress(&cinfo);
-
- alwaysAssertM(this, "Corrupt GImage");
- // Release JPEG decompression object
- jpeg_destroy_decompress(&cinfo);
-}
-
-
-}
diff --git a/dep/g3dlite/source/GImage_png.cpp b/dep/g3dlite/source/GImage_png.cpp
deleted file mode 100644
index 875c7015cd1..00000000000
--- a/dep/g3dlite/source/GImage_png.cpp
+++ /dev/null
@@ -1,276 +0,0 @@
-/**
- @file GImage_png.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-04-20
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-#include <png.h>
-
-namespace G3D {
-
-
-//libpng required function signature
-static void png_read_data(
- png_structp png_ptr,
- png_bytep data,
- png_size_t length) {
-
-
- debugAssert( png_ptr->io_ptr != NULL );
- debugAssert( length >= 0 );
- debugAssert( data != NULL );
-
- ((BinaryInput*)png_ptr->io_ptr)->readBytes(data, length);
-}
-
-//libpng required function signature
-static void png_write_data(png_structp png_ptr,
- png_bytep data,
- png_size_t length) {
-
- debugAssert( png_ptr->io_ptr != NULL );
- debugAssert( data != NULL );
-
- ((BinaryOutput*)png_ptr->io_ptr)->writeBytes(data, length);
-}
-
-//libpng required function signature
-static void png_flush_data(
- png_structp png_ptr) {
- (void)png_ptr;
- //Do nothing.
-}
-
-//libpng required function signature
-static void png_error(
- png_structp png_ptr,
- png_const_charp error_msg) {
-
- (void)png_ptr;
- debugAssert( error_msg != NULL );
- throw GImage::Error(error_msg, "PNG");
-}
-
-
-//libpng required function signature
-void png_warning(
- png_structp png_ptr,
- png_const_charp warning_msg) {
-
- (void)png_ptr;
- debugAssert( warning_msg != NULL );
- Log::common()->println(warning_msg);
-}
-
-
-void GImage::encodePNG(
- BinaryOutput& out) const {
-
- if (! (m_channels == 1 || m_channels == 3 || m_channels == 4)) {
- throw GImage::Error(format("Illegal channels for PNG: %d", m_channels), out.getFilename());
- }
- if (m_width <= 0) {
- throw GImage::Error(format("Illegal width for PNG: %d", m_width), out.getFilename());
- }
- if (m_height <= 0) {
- throw GImage::Error(format("Illegal height for PNG: %d", m_height), out.getFilename());
- }
-
- // PNG library requires that the height * pointer size fit within an int
- if (png_uint_32(m_height) * png_sizeof(png_bytep) > PNG_UINT_32_MAX) {
- throw GImage::Error("Unsupported PNG height.", out.getFilename());
- }
-
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning);
- if (! png_ptr) {
- throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename());
- }
-
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (! info_ptr) {
- png_destroy_write_struct(&png_ptr, &info_ptr);
- throw GImage::Error("Unable to initialize PNG encoder.", out.getFilename());
- }
-
- //setup libpng write handler so can use BinaryOutput
- png_set_write_fn(png_ptr, (void*)&out, png_write_data, png_flush_data);
- png_color_8_struct sig_bit;
-
- switch (m_channels) {
- case 1:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_GRAY,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- sig_bit.red = 0;
- sig_bit.green = 0;
- sig_bit.blue = 0;
- sig_bit.alpha = 0;
- sig_bit.gray = 8;
- break;
-
- case 3:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_RGB,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
-
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- sig_bit.alpha = 0;
- sig_bit.gray = 0;
- break;
-
- case 4:
- png_set_IHDR(png_ptr, info_ptr, m_width, m_height, 8, PNG_COLOR_TYPE_RGBA,
- PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
- sig_bit.red = 8;
- sig_bit.green = 8;
- sig_bit.blue = 8;
- sig_bit.alpha = 8;
- sig_bit.gray = 0;
- break;
-
- default:
- png_destroy_write_struct(&png_ptr, &info_ptr);
- throw GImage::Error("Unsupported number of channels for PNG.", out.getFilename());
- }
-
-
- png_set_sBIT(png_ptr, info_ptr, &sig_bit);
-
- //write the png header
- png_write_info(png_ptr, info_ptr);
-
- png_bytepp row_pointers = new png_bytep[m_height];
-
- for (int i=0; i < m_height; ++i) {
- row_pointers[i] = (png_bytep)&m_byte[m_width * m_channels * i];
- }
-
- png_write_image(png_ptr, row_pointers);
-
- png_write_end(png_ptr, info_ptr);
-
- delete[] row_pointers;
-
- png_destroy_write_struct(&png_ptr, &info_ptr);
-}
-
-
-void GImage::decodePNG(
- BinaryInput& input) {
-
- png_structp png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, png_error, png_warning);
- if (png_ptr == NULL) {
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- png_infop info_ptr = png_create_info_struct(png_ptr);
- if (info_ptr == NULL) {
- png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- png_infop end_info = png_create_info_struct(png_ptr);
- if (end_info == NULL) {
- png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
- throw GImage::Error("Unable to initialize PNG decoder.", input.getFilename());
- }
-
- // now that the libpng structures are setup, change the error handlers and read routines
- // to use G3D functions so that BinaryInput can be used.
-
- png_set_read_fn(png_ptr, (png_voidp)&input, png_read_data);
-
- // read in sequentially so that three copies of the file are not in memory at once
- png_read_info(png_ptr, info_ptr);
-
- png_uint_32 png_width, png_height;
- int bit_depth, color_type, interlace_type;
- // this will validate the data it extracts from info_ptr
- png_get_IHDR(png_ptr, info_ptr, &png_width, &png_height, &bit_depth, &color_type,
- &interlace_type, NULL, NULL);
-
- if (color_type == PNG_COLOR_TYPE_GRAY_ALPHA) {
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
- throw GImage::Error("Unsupported PNG color type - PNG_COLOR_TYPE_GRAY_ALPHA.", input.getFilename());
- }
-
- m_width = static_cast<uint32>(png_width);
- m_height = static_cast<uint32>(png_height);
-
- //swap bytes of 16 bit files to least significant byte first
- png_set_swap(png_ptr);
-
- png_set_strip_16(png_ptr);
-
- //Expand paletted colors into true RGB triplets
- if (color_type == PNG_COLOR_TYPE_PALETTE) {
- png_set_palette_to_rgb(png_ptr);
- }
-
- //Expand grayscale images to the full 8 bits from 1, 2, or 4 bits/pixel
- if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 8) {
- png_set_expand(png_ptr);
- }
-
- //Expand paletted or RGB images with transparency to full alpha channels
- //so the data will be available as RGBA quartets.
- if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS)) {
- png_set_tRNS_to_alpha(png_ptr);
- }
-
- // Fix sub-8 bit_depth to 8bit
- if (bit_depth < 8) {
- png_set_packing(png_ptr);
- }
-
- if ((color_type == PNG_COLOR_TYPE_RGBA) ||
- ((color_type == PNG_COLOR_TYPE_PALETTE) && (png_ptr->num_trans > 0)) ) {
-
- m_channels = 4;
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 4);
-
- } else if ((color_type == PNG_COLOR_TYPE_RGB) ||
- (color_type == PNG_COLOR_TYPE_PALETTE)) {
-
- m_channels = 3;
- m_byte = (uint8*)System::malloc(m_width * m_height * 3);
-
- } else if (color_type == PNG_COLOR_TYPE_GRAY) {
-
- m_channels = 1;
-
- // Round up to the nearest 8 rows to avoid a bug in the PNG decoder
- int h = iCeil(m_height / 8) * 8;
- int sz = m_width * h;
- m_byte = (uint8*)m_memMan->alloc(sz);
-
- } else {
- throw GImage::Error("Unsupported PNG bit-depth or type.", input.getFilename());
- }
-
- //since we are reading row by row, required to handle interlacing
- uint32 number_passes = png_set_interlace_handling(png_ptr);
-
- png_read_update_info(png_ptr, info_ptr);
-
- for (uint32 pass = 0; pass < number_passes; ++pass) {
- for (uint32 y = 0; y < (uint32)m_height; ++y) {
- png_bytep rowPointer = &m_byte[m_width * m_channels * y];
- png_read_rows(png_ptr, &rowPointer, NULL, 1);
- }
- }
-
-// png_read_image(png_ptr, &_byte);
- png_read_end(png_ptr, info_ptr);
-
- png_destroy_read_struct(&png_ptr, &info_ptr, &end_info);
-}
-
-}
diff --git a/dep/g3dlite/source/GImage_ppm.cpp b/dep/g3dlite/source/GImage_ppm.cpp
deleted file mode 100644
index f3065c6038b..00000000000
--- a/dep/g3dlite/source/GImage_ppm.cpp
+++ /dev/null
@@ -1,217 +0,0 @@
-/**
- @file GImage_ppm.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2006-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/TextInput.h"
-#include "G3D/TextOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-void GImage::encodePPMASCII(
- BinaryOutput& out) const {
-
- TextOutput::Settings ppmOptions;
- ppmOptions.convertNewlines = false;
- ppmOptions.numColumns = 70;
- ppmOptions.wordWrap = TextOutput::Settings::WRAP_WITHOUT_BREAKING;
- TextOutput ppm(ppmOptions);
-
- switch (m_channels) {
- case 1:
- {
- ppm.printf("P2\n%d %d\n255\n", m_width, m_height);
-
- const Color1uint8* c = this->pixel1();
- // Insert newlines every 70 characters max
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- ppm.printf("%d%c", c[i].value, (i % (70/4) == 0) ? '\n' : ' ');
- }
- }
- break;
-
- case 3:
- {
- ppm.printf("P3\n%d %d\n255\n", m_width, m_height);
-
- const Color3uint8* c = this->pixel3();
- // Insert newlines every 70 characters max
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- ppm.printf("%d %d %d%c", c[i].r, c[i].g, c[i].b,
- (i % (70/12) == 0) ?
- '\n' : ' ');
- }
- }
- break;
- default:
- alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
- }
-
- const std::string& s = ppm.commitString();
- out.writeBytes(s.c_str(), s.length());
-}
-
-
-void GImage::encodePPM(
- BinaryOutput& out) const {
-
- // http://netpbm.sourceforge.net/doc/ppm.html
- if (m_channels == 3) {
- std::string header = format("P6 %d %d 255 ", m_width, m_height);
- out.writeBytes(header.c_str(), header.size());
- out.writeBytes(this->pixel3(), m_width * m_height * 3);
- } else if (m_channels == 1) {
- std::string header = format("P5 %d %d 255 ", m_width, m_height);
- out.writeBytes(header.c_str(), header.size());
- out.writeBytes(this->pixel1(), m_width * m_height);
- } else {
- alwaysAssertM(false, "PPM requires either 1 or 3 channels exactly.");
- }
-}
-
-
-void GImage::decodePPMASCII(
- BinaryInput& input) {
-
- int ppmWidth;
- int ppmHeight;
-
- double maxColor;
-
- // Create a TextInput object to parse ascii format
- // Mixed binary/ascii formats will require more
-
- const std::string inputStr = input.readString();
-
- TextInput::Settings ppmOptions;
- ppmOptions.cppLineComments = false;
- ppmOptions.otherCommentCharacter = '#';
- ppmOptions.signedNumbers = true;
- ppmOptions.singleQuotedStrings = false;
-
- TextInput ppmInput(TextInput::FROM_STRING, inputStr, ppmOptions);
-
- //Skip first line in header P#
- std::string ppmType = ppmInput.readSymbol();
-
- ppmWidth = (int)ppmInput.readNumber();
- ppmHeight = (int)ppmInput.readNumber();
-
- // Everything but a PBM will have a max color value
- if (ppmType != "P2") {
- maxColor = ppmInput.readNumber();
- } else {
- maxColor = 255;
- }
-
- if ((ppmWidth < 0) ||
- (ppmHeight < 0) ||
- (maxColor <= 0)) {
- throw GImage::Error("Invalid PPM Header.", input.getFilename());
- }
-
- // I don't think it's proper to scale values less than 255
- if (maxColor <= 255.0) {
- maxColor = 255.0;
- }
-
- m_width = ppmWidth;
- m_height = ppmHeight;
- m_channels = 3;
- // always scale down to 1 byte per channel
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * 3);
-
- // Read in the image data. I am not validating if the values match the maxColor
- // requirements. I only scale if needed to fit within the byte available.
- for (uint32 i = 0; i < (uint32)(m_width * m_height); ++i) {
- // read in color and scale to max pixel defined in header
- // A max color less than 255 might need to be left alone and not scaled.
- Color3uint8& curPixel = *(pixel3() + i);
-
- if (ppmType == "P3") {
- curPixel.r = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.g = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.b = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- } else if (ppmType == "P2") {
- uint8 pixel = (uint8)(ppmInput.readNumber() * (255.0 / maxColor));
- curPixel.r = pixel;
- curPixel.g = pixel;
- curPixel.b = pixel;
- } else if (ppmType == "P1") {
- int pixel = (uint8)(ppmInput.readNumber() * maxColor);
- curPixel.r = pixel;
- curPixel.g = pixel;
- curPixel.b = pixel;
- }
- }
-}
-
-/** Consumes whitespace up to and including a number, but not the following character */
-static int scanUInt(BinaryInput& input) {
- char c = input.readUInt8();
- while (isWhiteSpace(c)) {
- c = input.readUInt8();
- }
-
- std::string s;
- s += c;
- c = input.readUInt8();
- while (!isWhiteSpace(c)) {
- s += c;
- c = input.readUInt8();
- }
-
- // Back up one to avoid consuming the last character
- input.setPosition(input.getPosition() - 1);
-
- int x;
- sscanf(s.c_str(), "%d", &x);
- return x;
-}
-
-
-void GImage::decodePPM(
- BinaryInput& input) {
-
- char head[2];
- int w, h;
-
- input.readBytes(head, 2);
- if (head[0] != 'P' || ((head[1] != '6') && (head[1] != '5'))) {
- throw GImage::Error("Invalid PPM Header.", input.getFilename());
- }
-
- w = scanUInt(input);
- h = scanUInt(input);
-
- // Skip the max color specifier
- scanUInt(input);
-
- if ((w < 0) ||
- (h < 0) ||
- (w > 100000) ||
- (h > 100000)) {
- throw GImage::Error("Invalid PPM size in header.", input.getFilename());
- }
-
- // Trailing whitespace
- input.readUInt8();
-
- if (head[1] == '6') {
- // 3 channel
- resize(w, h, 3);
- input.readBytes(m_byte, m_width * m_height * 3);
- } else if (head[1] == '5') {
- // 1 channel
- resize(w, h, 1);
- input.readBytes(m_byte, m_width * m_height);
- }
-}
-
-}
diff --git a/dep/g3dlite/source/GImage_tga.cpp b/dep/g3dlite/source/GImage_tga.cpp
deleted file mode 100644
index fdcd59af726..00000000000
--- a/dep/g3dlite/source/GImage_tga.cpp
+++ /dev/null
@@ -1,236 +0,0 @@
-/**
- @file GImage_tga.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-05-27
- @edited 2009-05-10
- */
-#include "G3D/platform.h"
-#include "G3D/GImage.h"
-#include "G3D/BinaryInput.h"
-#include "G3D/BinaryOutput.h"
-#include "G3D/Log.h"
-
-namespace G3D {
-
-void GImage::encodeTGA(
- BinaryOutput& out) const {
-
- out.setEndian(G3D_LITTLE_ENDIAN);
-
- // ID length
- out.writeUInt8(0);
-
- // Color map Type
- out.writeUInt8(0);
-
- // Type
- out.writeUInt8(2);
-
- // Color map
- out.skip(5);
-
- // x, y offsets
- out.writeUInt16(0);
- out.writeUInt16(0);
-
- // Width & height
- out.writeUInt16(m_width);
- out.writeUInt16(m_height);
-
- // Color depth
- if (m_channels == 1) {
- // Force RGB mode
- out.writeUInt8(8 * 3);
- } else {
- out.writeUInt8(8 * m_channels);
- }
-
- // Image descriptor
- if (m_channels < 4) {
- // 0 alpha bits
- out.writeUInt8(0);
- } else {
- // 8 alpha bits
- out.writeUInt8(8);
- }
-
- // Image ID (zero length)
-
- if (m_channels == 1) {
- // Pixels are upside down in BGR format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8 p = (m_byte[(y * m_width + x)]);
- out.writeUInt8(p);
- out.writeUInt8(p);
- out.writeUInt8(p);
- }
- }
- } else if (m_channels == 3) {
- // Pixels are upside down in BGR format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* p = &(m_byte[3 * (y * m_width + x)]);
- out.writeUInt8(p[2]);
- out.writeUInt8(p[1]);
- out.writeUInt8(p[0]);
- }
- }
- } else {
- // Pixels are upside down in BGRA format.
- for (int y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; ++x) {
- uint8* p = &(m_byte[4 * (y * m_width + x)]);
- out.writeUInt8(p[2]);
- out.writeUInt8(p[1]);
- out.writeUInt8(p[0]);
- out.writeUInt8(p[3]);
- }
- }
- }
-
- // Write "TRUEVISION-XFILE " 18 bytes from the end
- // (with null termination)
- out.writeString("TRUEVISION-XFILE ");
-}
-
-inline static void readBGR(uint8* byte, BinaryInput& bi) {
- int b = bi.readUInt8();
- int g = bi.readUInt8();
- int r = bi.readUInt8();
-
- byte[0] = r;
- byte[1] = g;
- byte[2] = b;
-}
-
-inline static void readBGRA(uint8* byte, BinaryInput& bi) {
- readBGR(byte, bi);
- byte[3] = bi.readUInt8();
-}
-
-void GImage::decodeTGA(
- BinaryInput& input) {
-
- // This is a simple TGA loader that can handle uncompressed
- // truecolor TGA files (TGA type 2).
- // Verify this is a TGA file by looking for the TRUEVISION tag.
- int pos = input.getPosition();
- input.setPosition(input.size() - 18);
- std::string tag = input.readString(16);
- if (tag != "TRUEVISION-XFILE") {
- throw Error("Not a TGA file", input.getFilename());
- }
-
- input.setPosition(pos);
-
- int IDLength = input.readUInt8();
- int colorMapType = input.readUInt8();
- int imageType = input.readUInt8();
-
- (void)colorMapType;
-
- // 2 is the type supported by this routine.
- if (imageType != 2 && imageType != 10) {
- throw Error("TGA images must be type 2 (Uncompressed truecolor) or 10 (Run-length truecolor)", input.getFilename());
- }
-
- // Color map specification
- input.skip(5);
-
- // Image specification
-
- // Skip x and y offsets
- input.skip(4);
-
- m_width = input.readInt16();
- m_height = input.readInt16();
-
- int colorDepth = input.readUInt8();
-
- if ((colorDepth != 24) && (colorDepth != 32)) {
- throw Error("TGA files must be 24 or 32 bit.", input.getFilename());
- }
-
- if (colorDepth == 32) {
- m_channels = 4;
- } else {
- m_channels = 3;
- }
-
- // Image descriptor contains overlay data as well
- // as data indicating where the origin is
- int imageDescriptor = input.readUInt8();
- (void)imageDescriptor;
-
- // Image ID
- input.skip(IDLength);
-
- m_byte = (uint8*)m_memMan->alloc(m_width * m_height * m_channels);
- debugAssert(m_byte);
-
- // Pixel data
- int x;
- int y;
-
- if (imageType == 2) {
- // Uncompressed
- if (m_channels == 3) {
- for (y = m_height - 1; y >= 0; --y) {
- for (x = 0; x < m_width; ++x) {
- int i = (x + y * m_width) * 3;
- readBGR(m_byte + i, input);
- }
- }
- } else {
- for (y = m_height - 1; y >= 0; --y) {
- for (x = 0; x < m_width; ++x) {
- int i = (x + y * m_width) * 4;
- readBGRA(m_byte + i, input);
- }
- }
- }
- } else if (imageType == 10) {
-
- // Run-length encoded
- for (y = m_height - 1; y >= 0; --y) {
- for (int x = 0; x < m_width; /* intentionally no x increment */) {
- // The specification guarantees that no packet will wrap past the end of a row
- const uint8 repetitionCount = input.readUInt8();
- const uint8 numValues = (repetitionCount & (~128)) + 1;
- int byteOffset = (x + y * m_width) * 3;
-
- if (repetitionCount & 128) {
- // When the high bit is 1, this is a run-length packet
- if (m_channels == 3) {
- Color3uint8 value;
- readBGR((uint8*)(&value), input);
- for (int i = 0; i < numValues; ++i, ++x) {
- for (int b = 0; b < 3; ++b, ++byteOffset) {
- m_byte[byteOffset] = value[b];
- }
- }
- } else {
- Color4uint8 value;
- readBGRA((uint8*)(&value), input);
- for (int i = 0; i < numValues; ++i, ++x) {
- for (int b = 0; b < 3; ++b, ++byteOffset) {
- m_byte[byteOffset] = value[b];
- }
- }
- }
-
- } else {
- // When the high bit is 0, this is a raw packet
- for (int i = 0; i < numValues; ++i, ++x, byteOffset += m_channels) {
- readBGR(m_byte + byteOffset, input);
- }
- }
- }
- }
- } else {
- alwaysAssertM(false, "Unsupported type");
- }
-}
-
-}
diff --git a/dep/g3dlite/source/GLight.cpp b/dep/g3dlite/source/GLight.cpp
deleted file mode 100644
index 553b493c1a3..00000000000
--- a/dep/g3dlite/source/GLight.cpp
+++ /dev/null
@@ -1,275 +0,0 @@
-/**
- @file GLight.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2003-11-12
- @edited 2009-11-16
-*/
-#include "G3D/GLight.h"
-#include "G3D/Sphere.h"
-#include "G3D/CoordinateFrame.h"
-#include "G3D/Any.h"
-#include "G3D/stringutils.h"
-
-namespace G3D {
-
-GLight::GLight(const Any& any) {
- any.verifyName("GLight");
-
- if (any.type() == Any::TABLE) {
- *this = GLight();
- Vector3 spotTarget;
- bool hasSpotTarget = false;
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& key = toLower(it->key);
- if (key == "position") {
- position = it->value;
- } else if (key == "rightdirection") {
- rightDirection = it->value;
- } else if (key == "spotdirection") {
- spotDirection = Vector3(it->value).directionOrZero();
- } else if (key == "spottarget") {
- spotTarget = it->value;
- hasSpotTarget = true;
- } else if (key == "spotcutoff") {
- spotCutoff = it->value.number();
- } else if (key == "spotsquare") {
- spotSquare = it->value.boolean();
- } else if (key == "attenuation") {
- attenuation[0] = it->value[0].number();
- attenuation[1] = it->value[1].number();
- attenuation[2] = it->value[2].number();
- } else if (key == "color") {
- color = it->value;
- } else if (key == "enabled") {
- enabled = it->value.boolean();
- } else if (key == "specular") {
- specular = it->value.boolean();
- } else if (key == "diffuse") {
- diffuse = it->value.boolean();
- } else {
- any.verify(false, "Illegal key: " + it->key);
- }
- }
- if (hasSpotTarget) {
- spotDirection = (spotTarget - position.xyz()).direction();
- }
- } else if (toLower(any.name()) == "glight::directional") {
-
- *this = directional(any[0], any[1],
- (any.size() > 2) ? any[2] : Any(true),
- (any.size() > 3) ? any[3] : Any(true));
-
- } else if (toLower(any.name()) == "glight::point") {
-
- *this = point(any[0], any[1],
- (any.size() > 2) ? any[2] : Any(1),
- (any.size() > 3) ? any[3] : Any(0),
- (any.size() > 4) ? any[4] : Any(0.5f),
- (any.size() > 5) ? any[5] : Any(true),
- (any.size() > 6) ? any[6] : Any(true));
-
- } else if (toLower(any.name()) == "glight::spot") {
-
- *this = spot(any[0], any[1], any[2], any[3],
- (any.size() > 4) ? any[4] : Any(1),
- (any.size() > 5) ? any[5] : Any(0),
- (any.size() > 6) ? any[6] : Any(0),
- (any.size() > 7) ? any[7] : Any(true),
- (any.size() > 8) ? any[8] : Any(true));
- } else {
- any.verify(false, "Unrecognized name");
- }
-}
-
-
-GLight::operator Any() const {
- Any a(Any::TABLE, "GLight");
- a.set("position", position.operator Any());
- a.set("rightDirection", rightDirection.operator Any());
- a.set("spotDirection", spotDirection.operator Any());
- a.set("spotCutoff", spotCutoff);
- a.set("spotSquare", spotSquare);
-
- Any att(Any::ARRAY);
- att.append(attenuation[0], attenuation[1], attenuation[2]);
- a.set("attenuation", att);
- a.set("color", color.operator Any());
- a.set("enabled", enabled);
- a.set("specular", specular);
- a.set("diffuse", diffuse);
- return a;
-}
-
-
-GLight::GLight() :
- position(0, 0, 0, 0),
- rightDirection(0,0,0),
- spotDirection(0, 0, -1),
- spotCutoff(180),
- spotSquare(false),
- color(Color3::white()),
- enabled(false),
- specular(true),
- diffuse(true) {
-
- attenuation[0] = 1.0;
- attenuation[1] = 0.0;
- attenuation[2] = 0.0;
-}
-
-
-GLight GLight::directional(const Vector3& toLight, const Color3& color, bool s, bool d) {
- GLight L;
- L.position = Vector4(toLight.direction(), 0);
- L.color = color;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-GLight GLight::point(const Vector3& pos, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) {
- GLight L;
- L.position = Vector4(pos, 1);
- L.color = color;
- L.attenuation[0] = constAtt;
- L.attenuation[1] = linAtt;
- L.attenuation[2] = quadAtt;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-GLight GLight::spot(const Vector3& pos, const Vector3& pointDirection, float cutOffAngleDegrees, const Color3& color, float constAtt, float linAtt, float quadAtt, bool s, bool d) {
- GLight L;
- L.position = Vector4(pos, 1.0f);
- L.spotDirection = pointDirection.direction();
- debugAssert(cutOffAngleDegrees <= 90);
- L.spotCutoff = cutOffAngleDegrees;
- L.color = color;
- L.attenuation[0] = constAtt;
- L.attenuation[1] = linAtt;
- L.attenuation[2] = quadAtt;
- L.specular = s;
- L.diffuse = d;
- return L;
-}
-
-
-bool GLight::operator==(const GLight& other) const {
- return (position == other.position) &&
- (rightDirection == other.rightDirection) &&
- (spotDirection == other.spotDirection) &&
- (spotCutoff == other.spotCutoff) &&
- (spotSquare == other.spotSquare) &&
- (attenuation[0] == other.attenuation[0]) &&
- (attenuation[1] == other.attenuation[1]) &&
- (attenuation[2] == other.attenuation[2]) &&
- (color == other.color) &&
- (enabled == other.enabled) &&
- (specular == other.specular) &&
- (diffuse == other.diffuse);
-}
-
-
-bool GLight::operator!=(const GLight& other) const {
- return !(*this == other);
-}
-
-
-Sphere GLight::effectSphere(float cutoff) const {
- if (position.w == 0) {
- // Directional light
- return Sphere(Vector3::zero(), finf());
- } else {
- // Avoid divide by zero
- cutoff = max(cutoff, 0.00001f);
- float maxIntensity = max(color.r, max(color.g, color.b));
-
- float radius = finf();
-
- if (attenuation[2] != 0) {
-
- // Solve I / attenuation.dot(1, r, r^2) < cutoff for r
- //
- // a[0] + a[1] r + a[2] r^2 > I/cutoff
- //
-
- float a = attenuation[2];
- float b = attenuation[1];
- float c = attenuation[0] - maxIntensity / cutoff;
-
- float discrim = square(b) - 4 * a * c;
-
- if (discrim >= 0) {
- discrim = sqrt(discrim);
-
- float r1 = (-b + discrim) / (2 * a);
- float r2 = (-b - discrim) / (2 * a);
-
- if (r1 < 0) {
- if (r2 > 0) {
- radius = r2;
- }
- } else if (r2 > 0) {
- radius = min(r1, r2);
- } else {
- radius = r1;
- }
- }
-
- } else if (attenuation[1] != 0) {
-
- // Solve I / attenuation.dot(1, r) < cutoff for r
- //
- // r * a[1] + a[0] = I / cutoff
- // r = (I / cutoff - a[0]) / a[1]
-
- float radius = (maxIntensity / cutoff - attenuation[0]) / attenuation[1];
- radius = max(radius, 0.0f);
- }
-
- return Sphere(position.xyz(), radius);
-
- }
-}
-
-
-CoordinateFrame GLight::frame() const {
- CoordinateFrame f;
- if (rightDirection == Vector3::zero()) {
- // No specified right direction; choose one automatically
- if (position.w == 0) {
- // Directional light
- f.lookAt(-position.xyz());
- } else {
- // Spot light
- f.lookAt(spotDirection);
- }
- } else {
- const Vector3& Z = -spotDirection.direction();
- Vector3 X = rightDirection.direction();
-
- // Ensure the vectors are not too close together
- while (abs(X.dot(Z)) > 0.9f) {
- X = Vector3::random();
- }
-
- // Ensure perpendicular
- X -= Z * Z.dot(X);
- const Vector3& Y = Z.cross(X);
-
- f.rotation.setColumn(Vector3::X_AXIS, X);
- f.rotation.setColumn(Vector3::Y_AXIS, Y);
- f.rotation.setColumn(Vector3::Z_AXIS, Z);
- }
- f.translation = position.xyz();
-
- return f;
-}
-
-
-} // G3D
diff --git a/dep/g3dlite/source/GThread.cpp b/dep/g3dlite/source/GThread.cpp
index 607e4b3572f..5f3f7ffd64e 100644
--- a/dep/g3dlite/source/GThread.cpp
+++ b/dep/g3dlite/source/GThread.cpp
@@ -4,7 +4,7 @@
GThread class.
@created 2005-09-24
- @edited 2005-10-22
+ @edited 2010-09-22
*/
#include "G3D/GThread.h"
@@ -38,7 +38,7 @@ GThread::GThread(const std::string& name):
m_status(STATUS_CREATED),
m_name(name) {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
m_event = NULL;
#endif
@@ -56,15 +56,16 @@ GThread::~GThread() {
# pragma warning( pop )
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
if (m_event) {
::CloseHandle(m_event);
}
#endif
}
+
GThreadRef GThread::create(const std::string& name, void (*proc)(void*), void* param) {
- return new _internal::BasicThread(name, proc, param);
+ return shared_ptr<GThread>(new _internal::BasicThread(name, proc, param));
}
@@ -72,6 +73,38 @@ bool GThread::started() const {
return m_status != STATUS_CREATED;
}
+
+int GThread::numCores() {
+ return System::numCores();
+}
+
+#ifdef G3D_WINDOWS
+// From http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
+const DWORD MS_VC_EXCEPTION=0x406D1388;
+
+#pragma pack(push,8)
+typedef struct tagTHREADNAME_INFO {
+ DWORD dwType; // Must be 0x1000.
+ LPCSTR szName; // Pointer to name (in user addr space).
+ DWORD dwThreadID; // Thread ID (-1=caller thread).
+ DWORD dwFlags; // Reserved for future use, must be zero.
+} THREADNAME_INFO;
+#pragma pack(pop)
+
+static void SetThreadName(DWORD dwThreadID, const char* threadName) {
+ THREADNAME_INFO info;
+ info.dwType = 0x1000;
+ info.szName = threadName;
+ info.dwThreadID = dwThreadID;
+ info.dwFlags = 0;
+
+ __try {
+ RaiseException( MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info );
+ } __except(EXCEPTION_EXECUTE_HANDLER) {}
+}
+#endif
+
+
bool GThread::start(SpawnBehavior behavior) {
debugAssertM(! started(), "Thread has already executed.");
@@ -89,7 +122,7 @@ bool GThread::start(SpawnBehavior behavior) {
return true;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
DWORD threadId;
m_event = ::CreateEvent(NULL, TRUE, FALSE, NULL);
@@ -102,6 +135,8 @@ bool GThread::start(SpawnBehavior behavior) {
m_event = NULL;
}
+ SetThreadName(threadId, m_name.c_str());
+
return (m_handle != NULL);
# else
if (!pthread_create(&m_handle, NULL, &internalThreadProc, this)) {
@@ -117,7 +152,7 @@ bool GThread::start(SpawnBehavior behavior) {
void GThread::terminate() {
if (m_handle) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
::TerminateThread(m_handle, 0);
# else
pthread_kill(m_handle, SIGSTOP);
@@ -144,7 +179,7 @@ void GThread::waitForCompletion() {
return;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
debugAssert(m_event);
::WaitForSingleObject(m_event, INFINITE);
# else
@@ -154,7 +189,7 @@ void GThread::waitForCompletion() {
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
DWORD WINAPI GThread::internalThreadProc(LPVOID param) {
GThread* current = reinterpret_cast<GThread*>(param);
debugAssert(current->m_event);
@@ -178,7 +213,7 @@ void* GThread::internalThreadProc(void* param) {
//GMutex implementation
GMutex::GMutex() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::InitializeCriticalSection(&m_handle);
#else
int ret = pthread_mutexattr_init(&m_attr);
@@ -192,7 +227,7 @@ GMutex::GMutex() {
GMutex::~GMutex() {
//TODO: Debug check for locked
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::DeleteCriticalSection(&m_handle);
#else
int ret = pthread_mutex_destroy(&m_handle);
@@ -203,7 +238,7 @@ GMutex::~GMutex() {
}
bool GMutex::tryLock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
return (::TryEnterCriticalSection(&m_handle) != 0);
#else
return (pthread_mutex_trylock(&m_handle) == 0);
@@ -211,7 +246,7 @@ bool GMutex::tryLock() {
}
void GMutex::lock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::EnterCriticalSection(&m_handle);
#else
pthread_mutex_lock(&m_handle);
@@ -219,7 +254,7 @@ void GMutex::lock() {
}
void GMutex::unlock() {
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
::LeaveCriticalSection(&m_handle);
#else
pthread_mutex_unlock(&m_handle);
diff --git a/dep/g3dlite/source/GUniqueID.cpp b/dep/g3dlite/source/GUniqueID.cpp
index 84c853e0e31..7dcc3ccd254 100644
--- a/dep/g3dlite/source/GUniqueID.cpp
+++ b/dep/g3dlite/source/GUniqueID.cpp
@@ -8,8 +8,27 @@
#include "G3D/BinaryOutput.h"
#include "G3D/TextOutput.h"
#include "G3D/NetworkDevice.h"
+#include "G3D/Any.h"
namespace G3D {
+
+GUniqueID& GUniqueID::operator=(const Any& a) {
+ a.verifyName("GUniqueID");
+ a.verifyType(Any::ARRAY);
+ a.verifySize(1);
+ std::string s = a[0];
+ a.verify(s.length() == 16);
+ id = GUniqueID::fromString16(s);
+ return *this;
+}
+
+
+Any GUniqueID::toAny() const {
+ Any a(Any::ARRAY, "GUniqueID");
+ a.append(toString16());
+ return a;
+}
+
void GUniqueID::serialize(BinaryOutput& b) const {
b.writeUInt64(id);
@@ -34,6 +53,33 @@ void GUniqueID::deserialize(TextInput& t) {
}
+GUniqueID GUniqueID::NONE(uint16 tag) {
+ GUniqueID i;
+ uint64 t = tag;
+ i.id = (t << 54);
+ return i;
+}
+
+
+std::string GUniqueID::toString16() const {
+ return format("%08x%08x", uint32(id >> 32), uint32(id & 0xFFFFFFFF));
+}
+
+
+GUniqueID GUniqueID::fromString16(const std::string& s) {
+ if (s.length() != 16) {
+ debugAssertM(false, "Corrupt 16-character string");
+ return GUniqueID();
+ }
+
+ uint32 high = 0, low = 0;
+ sscanf(s.c_str(), "%08x%08x", &high, &low);
+ GUniqueID i;
+ i.id = (uint64(high) << 32) | low;
+ return i;
+}
+
+
GUniqueID GUniqueID::create(uint16 tag) {
static uint64 counter = 0;
static uint64 systemID = 0;
diff --git a/dep/g3dlite/source/Image1.cpp b/dep/g3dlite/source/Image1.cpp
index a61f7faa633..ed125adad18 100644
--- a/dep/g3dlite/source/Image1.cpp
+++ b/dep/g3dlite/source/Image1.cpp
@@ -1,21 +1,23 @@
/**
- @file Image1.cpp
+ \file G3D/Image1.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2007-01-31
- @edited 2007-01-31
+ \created 2007-01-31
+ \edited 2012-12-25
*/
#include "G3D/Image1.h"
-#include "G3D/Image1uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image1unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image1::Image1(int w, int h, WrapMode wrap) : Map2D<Color1, Color1>(w, h, wrap)
}
-Image1::Ref Image1::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image1::Ref Image1::fromImage1uint8(const ReferenceCountedPointer<Image1uint8>& im) {
+Image1::Ref Image1::fromImage1unorm8(const shared_ptr<Image1unorm8>& im) {
Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color1uint8* src = reinterpret_cast<Color1uint8*>(im->getCArray());
+ const Color1unorm8* src = reinterpret_cast<Color1unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color1(src[i]);
}
@@ -57,7 +41,7 @@ Image1::Ref Image1::fromImage1uint8(const ReferenceCountedPointer<Image1uint8>&
Image1::Ref Image1::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
+ return Image1::Ref(new Type(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image1::Ref Image1::createEmpty(WrapMode wrap) {
}
-Image1::Ref Image1::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image1::Ref Image1::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
- out->load(filename, fmt);
+ out->load(filename);
return out;
}
-void Image1::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image1::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::L32F()) {
+ image->convertToL8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image1::Ref Image1::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image1::Ref Image1::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image1::Ref Image1::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image1::Ref Image1::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image1::Ref Image1::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image1::Ref Image1::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -120,24 +133,7 @@ Image1::Ref Image1::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
return out;
}
-void Image1::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image1::copyArray(const Color3uint8* src, int w, int h) {
+void Image1::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -149,7 +145,7 @@ void Image1::copyArray(const Color3uint8* src, int w, int h) {
}
-void Image1::copyArray(const Color4uint8* src, int w, int h) {
+void Image1::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -181,7 +177,7 @@ void Image1::copyArray(const Color4* src, int w, int h) {
}
-void Image1::copyArray(const Color1uint8* src, int w, int h) {
+void Image1::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -203,17 +199,10 @@ void Image1::copyArray(const Color3* src, int w, int h) {
}
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image1::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 1);
-
- int N = im.width() * im.height();
- Color1uint8* dst = im.pixel1();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image1::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to L8.
+ Image1unorm8::Ref unorm8 = Image1unorm8::fromImage1(dynamic_pointer_cast<Image1>(shared_from_this()));
+ unorm8->save(filename);
}
diff --git a/dep/g3dlite/source/Image1uint8.cpp b/dep/g3dlite/source/Image1uint8.cpp
deleted file mode 100644
index de2cbbc130b..00000000000
--- a/dep/g3dlite/source/Image1uint8.cpp
+++ /dev/null
@@ -1,212 +0,0 @@
-/**
- @file Image1uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-01-13
-*/
-
-#include "G3D/Image1uint8.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image1.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image1uint8::Image1uint8(int w, int h, WrapMode wrap) : Map2D<Color1uint8, Color1>(w, h, wrap) {
- setAll(Color1uint8(0));
-}
-
-
-Image1uint8::Ref Image1uint8::fromImage3uint8(const ReferenceCountedPointer<class Image3uint8>& im) {
- return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode());
-}
-
-
-Image1uint8::Ref Image1uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image1uint8::Ref Image1uint8::fromImage1(const ReferenceCountedPointer<Image1>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image1uint8::Ref Image1uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image1uint8::Ref Image1uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image1uint8::Ref Image1uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image1uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image1uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image1uint8::copyArray(const Color3uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].value = (src[i].r + src[i].g + src[i].b) / 3;
- }
-}
-
-void Image1uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(Color1(src[i].average()));
- }
-}
-
-
-void Image1uint8::copyArray(const Color1uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h);
-}
-
-
-void Image1uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(src[i]);
- }
-}
-
-
-void Image1uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].value = (ptr[i].r + ptr[i].g + ptr[i].b) / 3;
- }
-}
-
-
-void Image1uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color1uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color1uint8(Color1(src[i].rgb().average()));
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image1uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 1);
- System::memcpy(im.byte(), getCArray(), width() * height());
- im.save(filename, fmt);
-}
-
-
-const ImageFormat* Image1uint8::format() const {
- return ImageFormat::L8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/Image3.cpp b/dep/g3dlite/source/Image3.cpp
index 0d85bdf45da..671ad4b84c7 100644
--- a/dep/g3dlite/source/Image3.cpp
+++ b/dep/g3dlite/source/Image3.cpp
@@ -4,18 +4,20 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2007-01-31
- @edited 2007-01-31
+ @edited 2012-12-25
*/
#include "G3D/Image3.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image3unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image3::Image3(int w, int h, WrapMode wrap) : Map2D<Color3, Color3>(w, h, wrap)
}
-Image3::Ref Image3::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image3::Ref Image3::fromImage3uint8(const ReferenceCountedPointer<Image3uint8>& im) {
+Image3::Ref Image3::fromImage3unorm8(const shared_ptr<Image3unorm8>& im) {
Ref out = createEmpty(im->wrapMode());
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color3uint8* src = reinterpret_cast<Color3uint8*>(im->getCArray());
+ const Color3unorm8* src = reinterpret_cast<Color3unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color3(src[i]);
}
@@ -57,7 +41,7 @@ Image3::Ref Image3::fromImage3uint8(const ReferenceCountedPointer<Image3uint8>&
Image3::Ref Image3::createEmpty(int width, int height, WrapMode wrap) {
- return new Image3(width, height, wrap);
+ return shared_ptr<Image3>(new Image3(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image3::Ref Image3::createEmpty(WrapMode wrap) {
}
-Image3::Ref Image3::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image3::Ref Image3::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
- out->load(filename, fmt);
+ out->load(filename);
return out;
}
-void Image3::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image3::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::RGB32F()) {
+ image->convertToRGB8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image3::Ref Image3::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image3::Ref Image3::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image3::Ref Image3::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image3::Ref Image3::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image3::Ref Image3::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image3::Ref Image3::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -121,24 +134,7 @@ Image3::Ref Image3::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
}
-void Image3::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image3::copyArray(const Color3uint8* src, int w, int h) {
+void Image3::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -150,7 +146,7 @@ void Image3::copyArray(const Color3uint8* src, int w, int h) {
}
-void Image3::copyArray(const Color4uint8* src, int w, int h) {
+void Image3::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -182,7 +178,7 @@ void Image3::copyArray(const Color4* src, int w, int h) {
}
-void Image3::copyArray(const Color1uint8* src, int w, int h) {
+void Image3::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -205,16 +201,10 @@ void Image3::copyArray(const Color1* src, int w, int h) {
/** Saves in any of the formats supported by G3D::GImage. */
-void Image3::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 3);
-
- int N = im.width() * im.height();
- Color3uint8* dst = im.pixel3();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image3::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to RGB8.
+ Image3unorm8::Ref unorm8 = Image3unorm8::fromImage3(dynamic_pointer_cast<Image3>(shared_from_this()));
+ unorm8->save(filename);
}
diff --git a/dep/g3dlite/source/Image3uint8.cpp b/dep/g3dlite/source/Image3uint8.cpp
deleted file mode 100644
index 86595bbd1f6..00000000000
--- a/dep/g3dlite/source/Image3uint8.cpp
+++ /dev/null
@@ -1,225 +0,0 @@
-/**
- @file Image3uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-01-08
-*/
-
-#include "G3D/Image1uint8.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image3.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image3uint8::Ref Image3uint8::fromImage1uint8(const ReferenceCountedPointer<class Image1uint8>& im) {
- return fromArray(im->getCArray(), im->width(), im->height(), im->wrapMode());
-}
-
-
-Image3uint8::Image3uint8(int w, int h, WrapMode wrap) : Map2D<Color3uint8>(w, h, wrap) {
- setAll(Color3::black());
-}
-
-
-Image3uint8::Ref Image3uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image3uint8::Ref Image3uint8::fromImage3(const ReferenceCountedPointer<Image3>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image3uint8::Ref Image3uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image3uint8::Ref Image3uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image3uint8::Ref Image3uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image3uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image3uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image3uint8::copyArray(const Color1uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = src[i].value;
- }
-}
-
-void Image3uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value;
- }
-}
-
-
-void Image3uint8::copyArray(const Color3uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h * 3);
-}
-
-
-void Image3uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(src[i]);
- }
-}
-
-
-void Image3uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
-
- // Copy 3/4 bytes
- GImage::RGBAtoRGB((const uint8*)ptr, (uint8*)getCArray(), w * h);
-}
-
-
-void Image3uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color3uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color3uint8(src[i].rgb());
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image3uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 3);
- System::memcpy(im.byte(), getCArray(), width() * height() * 3);
- im.save(filename, fmt);
-}
-
-
-ReferenceCountedPointer<class Image1uint8> Image3uint8::getChannel(int c) const {
- debugAssert(c >= 0 && c <= 2);
-
- Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode());
- const Color3uint8* srcArray = getCArray();
- Color1uint8* dstArray = dst->getCArray();
-
- const int N = width() * height();
- for (int i = 0; i < N; ++i) {
- dstArray[i] = Color1uint8(srcArray[i][c]);
- }
-
- return dst;
-}
-
-
-const ImageFormat* Image3uint8::format() const {
- return ImageFormat::RGB8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/Image4.cpp b/dep/g3dlite/source/Image4.cpp
index c6f2b10640d..fa36050d370 100644
--- a/dep/g3dlite/source/Image4.cpp
+++ b/dep/g3dlite/source/Image4.cpp
@@ -4,18 +4,20 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2007-01-31
- @edited 2008-07-27
+ @edited 2011-08-27
*/
#include "G3D/Image4.h"
-#include "G3D/Image4uint8.h"
-#include "G3D/GImage.h"
+#include "G3D/Image4unorm8.h"
+#include "G3D/Image.h"
#include "G3D/Color3.h"
-#include "G3D/Color3uint8.h"
+#include "G3D/Color3unorm8.h"
#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
+#include "G3D/Color1unorm8.h"
#include "G3D/ImageFormat.h"
+#include "G3D/PixelTransferBuffer.h"
+#include "G3D/CPUPixelTransferBuffer.h"
namespace G3D {
@@ -24,30 +26,12 @@ Image4::Image4(int w, int h, WrapMode wrap) : Map2D<Color4, Color4>(w, h, wrap)
}
-Image4::Ref Image4::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image4::Ref Image4::fromImage4uint8(const ReferenceCountedPointer<Image4uint8>& im) {
+Image4::Ref Image4::fromImage4unorm8(const shared_ptr<Image4unorm8>& im) {
Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
out->resize(im->width(), im->height());
int N = im->width() * im->height();
- const Color4uint8* src = reinterpret_cast<Color4uint8*>(im->getCArray());
+ const Color4unorm8* src = reinterpret_cast<Color4unorm8*>(im->getCArray());
for (int i = 0; i < N; ++i) {
out->data[i] = Color4(src[i]);
}
@@ -57,7 +41,7 @@ Image4::Ref Image4::fromImage4uint8(const ReferenceCountedPointer<Image4uint8>&
Image4::Ref Image4::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
+ return shared_ptr<Image4>(new Type(width, height, wrap));
}
@@ -66,20 +50,49 @@ Image4::Ref Image4::createEmpty(WrapMode wrap) {
}
-Image4::Ref Image4::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
+Image4::Ref Image4::fromFile(const std::string& filename, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->load(filename);
return out;
}
-void Image4::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
+void Image4::load(const std::string& filename) {
+ shared_ptr<Image> image = Image::fromFile(filename);
+ if (image->format() != ImageFormat::RGBA32F()) {
+ image->convertToRGBA8();
+ }
+
+ switch (image->format()->code)
+ {
+ case ImageFormat::CODE_L8:
+ copyArray(static_cast<const Color1unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_L32F:
+ copyArray(static_cast<const Color1*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB8:
+ copyArray(static_cast<const Color3unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGB32F:
+ copyArray(static_cast<const Color3*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA8:
+ copyArray(static_cast<const Color4unorm8*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ case ImageFormat::CODE_RGBA32F:
+ copyArray(static_cast<const Color4*>(image->toPixelTransferBuffer()->buffer()), image->width(), image->height());
+ break;
+ default:
+ debugAssertM(false, "Trying to load unsupported image format");
+ break;
+ }
+
setChanged(true);
}
-Image4::Ref Image4::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color3unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -93,7 +106,7 @@ Image4::Ref Image4::fromArray(const class Color1* ptr, int w, int h, WrapMode wr
}
-Image4::Ref Image4::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color1unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -107,7 +120,7 @@ Image4::Ref Image4::fromArray(const class Color3* ptr, int w, int h, WrapMode wr
}
-Image4::Ref Image4::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
+Image4::Ref Image4::fromArray(const class Color4unorm8* ptr, int w, int h, WrapMode wrap) {
Ref out = createEmpty(wrap);
out->copyArray(ptr, w, h);
return out;
@@ -121,24 +134,7 @@ Image4::Ref Image4::fromArray(const class Color4* ptr, int w, int h, WrapMode wr
}
-void Image4::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image4::copyArray(const Color4uint8* src, int w, int h) {
+void Image4::copyArray(const Color4unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -150,7 +146,7 @@ void Image4::copyArray(const Color4uint8* src, int w, int h) {
}
-void Image4::copyArray(const Color3uint8* src, int w, int h) {
+void Image4::copyArray(const Color3unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -182,7 +178,7 @@ void Image4::copyArray(const Color3* src, int w, int h) {
}
-void Image4::copyArray(const Color1uint8* src, int w, int h) {
+void Image4::copyArray(const Color1unorm8* src, int w, int h) {
resize(w, h);
int N = w * h;
@@ -207,16 +203,10 @@ void Image4::copyArray(const Color1* src, int w, int h) {
/** Saves in any of the formats supported by G3D::GImage. */
-void Image4::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 4);
-
- int N = im.width() * im.height();
- Color4uint8* dst = im.pixel4();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(data[i]);
- }
-
- im.save(filename, fmt);
+void Image4::save(const std::string& filename) {
+ // To avoid saving as floating point image. FreeImage cannot convert floating point to RGBA8.
+ Image4unorm8::Ref unorm8 = Image4unorm8::fromImage4(dynamic_pointer_cast<Image4>(shared_from_this()));
+ unorm8->save(filename);
}
const ImageFormat* Image4::format() const {
diff --git a/dep/g3dlite/source/Image4uint8.cpp b/dep/g3dlite/source/Image4uint8.cpp
deleted file mode 100644
index a94ddb12d03..00000000000
--- a/dep/g3dlite/source/Image4uint8.cpp
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- @file Image4uint8.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-01-31
- @edited 2008-07-31
-*/
-
-#include "G3D/Image4uint8.h"
-#include "G3D/Image4.h"
-#include "G3D/Image3uint8.h"
-#include "G3D/Image3.h"
-#include "G3D/GImage.h"
-#include "G3D/Color1.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color4.h"
-#include "G3D/Color4uint8.h"
-#include "G3D/ImageFormat.h"
-
-namespace G3D {
-
-Image4uint8::Image4uint8(int w, int h, WrapMode wrap) : Map2D<Color4uint8, Color4>(w, h, wrap) {
- setAll(Color4::zero());
-}
-
-
-Image4uint8::Ref Image4uint8::fromGImage(const GImage& im, WrapMode wrap) {
- switch (im.channels()) {
- case 1:
- return fromArray(im.pixel1(), im.width(), im.height(), wrap);
-
- case 3:
- return fromArray(im.pixel3(), im.width(), im.height(), wrap);
-
- case 4:
- return fromArray(im.pixel4(), im.width(), im.height(), wrap);
-
- default:
- debugAssertM(false, "Input GImage must have 1, 3, or 4 channels.");
- return NULL;
- }
-}
-
-
-Image4uint8::Ref Image4uint8::fromImage4(const ReferenceCountedPointer<Image4>& im) {
- Ref out = createEmpty(static_cast<WrapMode>(im->wrapMode()));
- out->copyArray(im->getCArray(), im->width(), im->height());
-
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::createEmpty(int width, int height, WrapMode wrap) {
- return new Type(width, height, wrap);
-}
-
-
-Image4uint8::Ref Image4uint8::createEmpty(WrapMode wrap) {
- return createEmpty(0, 0, wrap);
-}
-
-
-Image4uint8::Ref Image4uint8::fromFile(const std::string& filename, WrapMode wrap, GImage::Format fmt) {
- Ref out = createEmpty(wrap);
- out->load(filename, fmt);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color3uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color1* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color1uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color3* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color4uint8* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-Image4uint8::Ref Image4uint8::fromArray(const class Color4* ptr, int w, int h, WrapMode wrap) {
- Ref out = createEmpty(wrap);
- out->copyArray(ptr, w, h);
- return out;
-}
-
-
-void Image4uint8::load(const std::string& filename, GImage::Format fmt) {
- copyGImage(GImage(filename, fmt));
- setChanged(true);
-}
-
-
-void Image4uint8::copyGImage(const GImage& im) {
- switch (im.channels()) {
- case 1:
- copyArray(im.pixel1(), im.width(), im.height());
- break;
-
- case 3:
- copyArray(im.pixel3(), im.width(), im.height());
- break;
-
- case 4:
- copyArray(im.pixel4(), im.width(), im.height());
- break;
- }
-}
-
-
-void Image4uint8::copyArray(const Color1uint8* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = src[i].value;
- dst[i].a = 255;
- }
-}
-
-void Image4uint8::copyArray(const Color1* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i].r = dst[i].g = dst[i].b = Color1uint8(src[i]).value;
- dst[i].a = 255;
- }
-}
-
-
-void Image4uint8::copyArray(const Color4uint8* ptr, int w, int h) {
- resize(w, h);
- System::memcpy(getCArray(), ptr, w * h * 4);
-}
-
-
-void Image4uint8::copyArray(const Color4* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(src[i]);
- }
-}
-
-
-void Image4uint8::copyArray(const Color3uint8* ptr, int w, int h) {
- resize(w, h);
-
- GImage::RGBtoRGBA((const uint8*)ptr, (uint8*)getCArray(), w * h);
-}
-
-
-void Image4uint8::copyArray(const Color3* src, int w, int h) {
- resize(w, h);
- int N = w * h;
-
- Color4uint8* dst = getCArray();
- for (int i = 0; i < N; ++i) {
- dst[i] = Color4uint8(Color4(src[i], 1.0f));
- }
-}
-
-
-/** Saves in any of the formats supported by G3D::GImage. */
-void Image4uint8::save(const std::string& filename, GImage::Format fmt) {
- GImage im(width(), height(), 4);
- System::memcpy(im.byte(), getCArray(), width() * height() * 4);
- im.save(filename, fmt);
-}
-
-
-ReferenceCountedPointer<class Image1uint8> Image4uint8::getChannel(int c) const {
- debugAssert(c >= 0 && c <= 3);
-
- Image1uint8Ref dst = Image1uint8::createEmpty(width(), height(), wrapMode());
- const Color4uint8* srcArray = getCArray();
- Color1uint8* dstArray = dst->getCArray();
-
- const int N = width() * height();
- for (int i = 0; i < N; ++i) {
- dstArray[i] = Color1uint8(srcArray[i][c]);
- }
-
- return dst;
-}
-
-
-const ImageFormat* Image4uint8::format() const {
- return ImageFormat::RGBA8();
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/ImageFormat.cpp b/dep/g3dlite/source/ImageFormat.cpp
index 46618c64480..0ffc27b661b 100644
--- a/dep/g3dlite/source/ImageFormat.cpp
+++ b/dep/g3dlite/source/ImageFormat.cpp
@@ -1,14 +1,15 @@
/**
- @file ImageFormat.cpp
+ \file ImageFormat.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-05-23
- @edited 2010-03-30
+ \created 2003-05-23
+ \edited 2013-01-12
*/
#include "GLG3D/glheaders.h"
#include "G3D/ImageFormat.h"
+#include "G3D/stringutils.h"
namespace G3D {
@@ -24,11 +25,11 @@ ImageFormat::ImageFormat(
int _blueBits,
int _depthBits,
int _stencilBits,
- int _hardwareBitsPerTexel,
- int _packedBitsPerTexel,
+ int _openGLBitsPerPixel,
+ int _cpuBitsPerPixel,
int glDataFormat,
bool _opaque,
- bool _floatingPoint,
+ NumberFormat _numberFormat,
Code _code,
ColorSpace _colorSpace,
BayerPattern _bayerPattern) :
@@ -47,17 +48,30 @@ ImageFormat::ImageFormat(
blueBits(_blueBits),
stencilBits(_stencilBits),
depthBits(_depthBits),
- cpuBitsPerPixel(_packedBitsPerTexel),
- packedBitsPerTexel(_packedBitsPerTexel),
- openGLBitsPerPixel(_hardwareBitsPerTexel),
- hardwareBitsPerTexel(_hardwareBitsPerTexel),
+ cpuBitsPerPixel(_cpuBitsPerPixel),
+ openGLBitsPerPixel(_openGLBitsPerPixel),
openGLDataFormat(glDataFormat),
opaque(_opaque),
- floatingPoint(_floatingPoint) {
+ numberFormat(_numberFormat){
- debugAssert(_packedBitsPerTexel <= _hardwareBitsPerTexel);
+ floatingPoint = (numberFormat == FLOATING_POINT_FORMAT);
+ debugAssert(cpuBitsPerPixel <= openGLBitsPerPixel);
}
+
+bool ImageFormat::sameComponents(const ImageFormat* other) const {
+ return
+ (numComponents == other->numComponents) &&
+ ((alphaBits != 0) == (other->alphaBits != 0)) &&
+ ((redBits != 0) == (other->redBits != 0)) &&
+ ((greenBits != 0) == (other->greenBits != 0)) &&
+ ((blueBits != 0) == (other->blueBits != 0)) &&
+ ((luminanceBits != 0) == (other->luminanceBits != 0)) &&
+ ((stencilBits != 0) == (other->stencilBits != 0)) &&
+ ((depthBits != 0) == (other->depthBits != 0));
+}
+
+
const ImageFormat* ImageFormat::depth(int depthBits) {
switch (depthBits) {
@@ -98,7 +112,7 @@ const ImageFormat* ImageFormat::stencil(int bits) {
}
- static const std::string nameArray[] =
+ static const std::string nameArray[ImageFormat::CODE_NUM] =
{
"L8",
"L16",
@@ -125,29 +139,62 @@ const ImageFormat* ImageFormat::stencil(int bits) {
"RGB16F",
"RGB32F",
"R11G11B10F",
- "RGB9E10F",
+ "RGB9E5F",
"RGB8I",
"RGB8UI",
+ "RGBA8I",
"RGBA8UI",
+ "RGB8_SNORM",
+ "RGBA8_SNORM",
+ "RGB16_SNORM",
+ "RGBA16_SNORM",
+
"ARGB8",
"BGR8",
+ "BGRA8",
"R8",
+ "R8I",
+ "R8UI",
+
+ "R16",
+ "R16I",
+ "R16UI",
+
+ "R32I",
+ "R32UI",
"RG8",
"RG8I",
"RG8UI",
+ "RG16",
+ "RG16I",
+ "RG16UI",
+
+ "R16F",
"RG16F",
+ "RG32I",
+ "RG32UI",
+
+ "R32F",
+ "RG32F",
+
"RGBA8",
"RGBA16",
"RGBA16F",
"RGBA32F",
+ "RGBA16I",
+ "RGBA16UI",
+
+ "RGB32I",
+ "RGB32UI",
+ "RGBA32I",
"RGBA32UI",
"BAYER_RGGB8",
@@ -192,8 +239,7 @@ const ImageFormat* ImageFormat::stencil(int bits) {
"STENCIL8",
"STENCIL16",
- "DEPTH24_STENCIL8",
- ""
+ "DEPTH24_STENCIL8"
};
const std::string& ImageFormat::name() const {
@@ -201,10 +247,148 @@ const std::string& ImageFormat::name() const {
return nameArray[code];
}
+bool ImageFormat::canInterpretAs(const ImageFormat* otherFormat) const {
+ if (this == otherFormat) {
+ return true;
+ }
+
+ if (compressed || otherFormat->compressed) {
+ return false;
+ }
+
+ if (colorSpace != otherFormat->colorSpace) {
+ return false;
+ }
+
+ if (floatingPoint != otherFormat->floatingPoint) {
+ return false;
+ }
+
+ if (numComponents != otherFormat->numComponents) {
+ return false;
+ }
+
+ if (cpuBitsPerPixel != otherFormat->cpuBitsPerPixel) {
+ return false;
+ }
+
+ if (openGLDataFormat != otherFormat->openGLDataFormat) {
+ return false;
+ }
+
+ return true;
+}
+
+
+const ImageFormat* ImageFormat::getSRGBFormat(const ImageFormat* otherFormat) {
+ switch (otherFormat->code) {
+ case CODE_RGB8:
+ return SRGB8();
+
+ case CODE_RGBA8:
+ return SRGBA8();
+
+ case CODE_RGB_DXT1:
+ return SRGB_DXT1();
+
+ case CODE_RGBA_DXT1:
+ return SRGBA_DXT1();
+
+ case CODE_RGBA_DXT3:
+ return SRGBA_DXT3();
+
+ case CODE_RGBA_DXT5:
+ return SRGBA_DXT5();
+
+ default:
+ return otherFormat;
+ }
+}
+
+
+const ImageFormat* ImageFormat::getFormatWithAlpha(const ImageFormat* otherFormat) {
+ if (! otherFormat->opaque) {
+ return otherFormat;
+ }
+
+ switch (otherFormat->code) {
+ case CODE_L8:
+ return LA8();
+ break;
+
+ case CODE_L16F:
+ return LA16F();
+ break;
+
+ case CODE_RGB8:
+ return RGBA8();
+ break;
+
+ case CODE_RGB8I:
+ return RGBA8I();
+ break;
+
+ case CODE_RGB32I:
+ return RGBA32I();
+ break;
+
+ case CODE_RGB32UI:
+ return RGBA32UI();
+ break;
+
+ case CODE_RGB8UI:
+ return RGBA8UI();
+ break;
+
+ case CODE_RGB8_SNORM:
+ return RGB8_SNORM();
+ break;
+ case CODE_RGBA8_SNORM:
+ return RGBA8_SNORM();
+ break;
+
+ case CODE_RGB16_SNORM:
+ return RGB16_SNORM();
+ break;
+
+ case CODE_RGBA16_SNORM:
+ return RGBA16_SNORM();
+ break;
+
+ case CODE_BGR8:
+ return BGRA8();
+ break;
+
+ case CODE_RGB16:
+ return RGBA16();
+ break;
+
+ case CODE_RGB16F:
+ return RGBA16F();
+ break;
+
+ case CODE_RGB32F:
+ return RGBA32F();
+ break;
+
+ case CODE_R11G11B10F:
+ return RGBA16F();
+ break;
+
+ default:
+ break;
+ }
+
+ return NULL;
+}
+
const ImageFormat* ImageFormat::fromString(const std::string& s) {
-
- for (int i = 0; ! nameArray[i].empty(); ++i) {
+ if (toLower(s) == "auto") {
+ return NULL;
+ }
+
+ for (int i = 0; i < CODE_NUM; ++i) {
if (s == nameArray[i]) {
return fromCode(ImageFormat::Code(i));
}
@@ -212,7 +396,6 @@ const ImageFormat* ImageFormat::fromString(const std::string& s) {
return NULL;
}
-
const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
switch (code) {
case ImageFormat::CODE_L8:
@@ -250,7 +433,7 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_LA16F:
return ImageFormat::LA16F();
- break;
+
case ImageFormat::CODE_LA32F:
return ImageFormat::LA32F();
@@ -287,15 +470,54 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RGB8UI:
return ImageFormat::RGB8UI();
+ case ImageFormat::CODE_RGBA8I:
+ return ImageFormat::RGBA8I();
+
+ case ImageFormat::CODE_RGBA8UI:
+ return ImageFormat::RGBA8UI();
+
+ case ImageFormat::CODE_RGB8_SNORM:
+ return ImageFormat::RGB8_SNORM();
+ case ImageFormat::CODE_RGBA8_SNORM:
+ return ImageFormat::RGBA8_SNORM();
+ case ImageFormat::CODE_RGB16_SNORM:
+ return ImageFormat::RGB16_SNORM();
+ case ImageFormat::CODE_RGBA16_SNORM:
+ return ImageFormat::RGBA16_SNORM();
+
case ImageFormat::CODE_ARGB8:
return NULL;
case ImageFormat::CODE_BGR8:
return ImageFormat::BGR8();
+ case ImageFormat::CODE_BGRA8:
+ return ImageFormat::BGRA8();
+
case ImageFormat::CODE_R8:
return ImageFormat::R8();
+ case ImageFormat::CODE_R8I:
+ return ImageFormat::R8I();
+
+ case ImageFormat::CODE_R8UI:
+ return ImageFormat::R8UI();
+
+ case ImageFormat::CODE_R16:
+ return ImageFormat::R16();
+
+ case ImageFormat::CODE_R16I:
+ return ImageFormat::R16I();
+
+ case ImageFormat::CODE_R16UI:
+ return ImageFormat::R16UI();
+
+ case ImageFormat::CODE_R32I:
+ return ImageFormat::R32I();
+
+ case ImageFormat::CODE_R32UI:
+ return ImageFormat::R32UI();
+
case ImageFormat::CODE_RG8:
return ImageFormat::RG8();
@@ -305,9 +527,18 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RG8UI:
return ImageFormat::RG8UI();
+ case ImageFormat::CODE_R16F:
+ return ImageFormat::R16F();
+
case ImageFormat::CODE_RG16F:
return ImageFormat::RG16F();
+ case ImageFormat::CODE_R32F:
+ return ImageFormat::R32F();
+
+ case ImageFormat::CODE_RG32F:
+ return ImageFormat::RG32F();
+
case ImageFormat::CODE_RGBA8:
return ImageFormat::RGBA8();
@@ -320,6 +551,15 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
case ImageFormat::CODE_RGBA32F:
return ImageFormat::RGBA32F();
+ case ImageFormat::CODE_RGB32I:
+ return ImageFormat::RGB32I();
+
+ case ImageFormat::CODE_RGBA32I:
+ return ImageFormat::RGBA32I();
+
+ case ImageFormat::CODE_RGB32UI:
+ return ImageFormat::RGB32UI();
+
case ImageFormat::CODE_RGBA32UI:
return ImageFormat::RGBA32UI();
@@ -439,11 +679,49 @@ const ImageFormat* ImageFormat::fromCode(ImageFormat::Code code) {
}
}
-// Helper variables for defining texture formats
-// Is floating point format
-static const bool FLOAT_FORMAT = true;
-static const bool INT_FORMAT = false;
+bool ImageFormat::representableAsColor1unorm8() const {
+ return (numComponents == 1) &&
+ (cpuBitsPerPixel == 8) &&
+ ((luminanceBits == 8) ||
+ (redBits == 8) ||
+ (alphaBits == 8));
+}
+
+
+bool ImageFormat::representableAsColor2unorm8() const {
+ return (numComponents == 2) &&
+ (cpuBitsPerPixel == 16) &&
+ ((redBits == 8 && greenBits == 8) ||
+ (luminanceBits == 8 && alphaBits == 8) ||
+ (redBits == 8 && alphaBits == 8));
+}
+
+
+bool ImageFormat::representableAsColor3unorm8() const {
+ return (numComponents == 3) &&
+ (cpuBitsPerPixel == 24) &&
+ (redBits == 8 && greenBits == 8 && blueBits == 8);
+}
+
+
+bool ImageFormat::representableAsColor4unorm8() const {
+ return (numComponents == 4) &&
+ (cpuBitsPerPixel == 32) &&
+ (redBits == 8 && greenBits == 8 && blueBits == 8 && alphaBits == 8);
+}
+
+Color4 ImageFormat::channelMask() const{
+ Color4 mask;
+ mask.r = (redBits > 0 || luminanceBits > 0) ? 1.0f : 0.0f;
+ mask.b = (blueBits > 0) ? 1.0f : 0.0f;
+ mask.g = (greenBits > 0) ? 1.0f : 0.0f;
+ mask.a = (alphaBits > 0) ? 1.0f : 0.0f;
+ return mask;
+
+}
+
+// Helper variables for defining texture formats
// Is opaque format (no alpha)
static const bool OPAQUE_FORMAT = true;
@@ -453,136 +731,176 @@ static const bool CLEAR_FORMAT = false;
static const bool COMP_FORMAT = true;
static const bool UNCOMP_FORMAT = false;
+
#define DEFINE_TEXTUREFORMAT_METHOD(enumname, cmpnts, cmprssd, glf, glbf, lb, ab, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs) \
const ImageFormat* ImageFormat::enumname() { \
static const ImageFormat format(cmpnts, cmprssd, glf, glbf, lb, ab, rb, gb, bb, db, sb, hbpt, pbpt, gldf, opq, fp, code, cs); \
return &format; }
-DEFINE_TEXTUREFORMAT_METHOD(L8, 1, UNCOMP_FORMAT, GL_LUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, CODE_L8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(L8, 1, UNCOMP_FORMAT, GL_LUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_L8, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L16, 1, UNCOMP_FORMAT, GL_LUMINANCE16, GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16,GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, CODE_L16, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L16F, 1, UNCOMP_FORMAT, GL_LUMINANCE16F_ARB,GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, CODE_L16F, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(L32F, 1, UNCOMP_FORMAT, GL_LUMINANCE32F_ARB,GL_LUMINANCE, 32, 0, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, CODE_L32F, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A8, 1, UNCOMP_FORMAT, GL_ALPHA8, GL_ALPHA, 0, 8, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_A8, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A16, 1, UNCOMP_FORMAT, GL_ALPHA16, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_A16, COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(A16F, 1, UNCOMP_FORMAT, GL_ALPHA16F_ARB, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, CODE_A16F, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L16, 1, UNCOMP_FORMAT, GL_LUMINANCE16, GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16,GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, CODE_L16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(A32F, 1, UNCOMP_FORMAT, GL_ALPHA32F_ARB, GL_ALPHA, 0, 32, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, CODE_A32F, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L16F, 1, UNCOMP_FORMAT, GL_LUMINANCE16F_ARB,GL_LUMINANCE, 16, 0, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L16F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA4, 2, UNCOMP_FORMAT, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 4, 4, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA4, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(L32F, 1, UNCOMP_FORMAT, GL_LUMINANCE32F_ARB,GL_LUMINANCE, 32, 0, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, CODE_L32F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA8, 2, UNCOMP_FORMAT, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA8, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A8, 1, UNCOMP_FORMAT, GL_ALPHA8, GL_ALPHA, 0, 8, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_A8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA16, 2, UNCOMP_FORMAT, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, CODE_LA16, COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A16, 1, UNCOMP_FORMAT, GL_ALPHA16, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_A16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA16F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_LA16F, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A16F, 1, UNCOMP_FORMAT, GL_ALPHA16F_ARB, GL_ALPHA, 0, 16, 0, 0, 0, 0, 0, 16, 16, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A16F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, 32, 32, 0, 0, 0, 0, 0, 32*2, 32*2, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_LA32F, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(A32F, 1, UNCOMP_FORMAT, GL_ALPHA32F_ARB, GL_ALPHA, 0, 32, 0, 0, 0, 0, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, CODE_A32F, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(BGR8, 3, UNCOMP_FORMAT, GL_RGB8, GL_BGR, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA4, 2, UNCOMP_FORMAT, GL_LUMINANCE4_ALPHA4, GL_LUMINANCE_ALPHA, 4, 4, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA4, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(BGRA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_BGRA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_BGRA8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA8, 2, UNCOMP_FORMAT, GL_LUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, CODE_LA8, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8, 1, UNCOMP_FORMAT, GL_R8, GL_RED, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA16, 2, UNCOMP_FORMAT, GL_LUMINANCE16_ALPHA16, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, CODE_LA16, COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8I, 1, UNCOMP_FORMAT, GL_R8I, GL_RED_INTEGER, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R8I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA16F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA16F_ARB, GL_LUMINANCE_ALPHA, 16, 16, 0, 0, 0, 0, 0, 16*2, 16*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA16F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R8UI, 1, UNCOMP_FORMAT, GL_R8UI, GL_RED_INTEGER, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R8UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(LA32F, 2, UNCOMP_FORMAT, GL_LUMINANCE_ALPHA32F_ARB, GL_LUMINANCE_ALPHA, 32, 32, 0, 0, 0, 0, 0, 32*2, 32*2, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_LA32F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(R16, 1, UNCOMP_FORMAT, GL_R16, GL_RED, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_R16, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(BGR8, 3, UNCOMP_FORMAT, GL_RGB8, GL_BGR, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_BGR8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16I, 1, UNCOMP_FORMAT, GL_R16I, GL_RED_INTEGER, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R16I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(R8, 1, UNCOMP_FORMAT, GL_R8, GL_RED, 0, 0, 8, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_R8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16UI, 1, UNCOMP_FORMAT, GL_R16UI, GL_RED_INTEGER, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG8, 2, UNCOMP_FORMAT, GL_RG8, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R32I, 1, UNCOMP_FORMAT, GL_R32I, GL_RED_INTEGER, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R32I, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(R32UI, 1, UNCOMP_FORMAT, GL_R32UI, GL_RED_INTEGER, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_R32UI, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG8, 2, UNCOMP_FORMAT, GL_RG8, GL_RG, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RG8, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG8I, 2, UNCOMP_FORMAT, GL_RG8I, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG8I, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RG16, 2, UNCOMP_FORMAT, GL_RG16, GL_RG, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RG16, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG8UI, 2, UNCOMP_FORMAT, GL_RG8UI, GL_RG_INTEGER, 0, 0, 8, 8, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RG8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16I, 2, UNCOMP_FORMAT, GL_RG16I, GL_RG_INTEGER, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG16I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RG16F, 2, UNCOMP_FORMAT, GL_RG16F, GL_RG, 0, 0, 16, 16, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RG16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16UI, 2, UNCOMP_FORMAT, GL_RG16UI, GL_RG_INTEGER, 0, 0, 16, 16, 0, 0, 0, 16*2, 16*2, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB5, 3, UNCOMP_FORMAT, GL_RGB5, GL_RGBA, 0, 0, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R16F, 1, UNCOMP_FORMAT, GL_R16F, GL_RED, 0, 0, 16, 0, 0, 0, 0, 16, 16, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R16F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB5A1, 4, UNCOMP_FORMAT, GL_RGB5_A1, GL_RGBA, 0, 1, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB5A1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG16F, 2, UNCOMP_FORMAT, GL_RG16F, GL_RG, 0, 0, 16, 16, 0, 0, 0, 32, 32, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RG16F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB8, 3, UNCOMP_FORMAT, GL_RGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32I, 2, UNCOMP_FORMAT, GL_RG32I, GL_RG_INTEGER, 0, 0, 32, 32, 0, 0, 0, 32*2, 32*2, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG32I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB10, 3, UNCOMP_FORMAT, GL_RGB10, GL_RGB, 0, 0, 10, 10, 10, 0, 0, 32, 10*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32UI, 2, UNCOMP_FORMAT, GL_RG32UI, GL_RG_INTEGER, 0, 0, 32, 32, 0, 0, 0, 32*2, 32*2, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RG32UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB10A2, 4, UNCOMP_FORMAT, GL_RGB10_A2, GL_RGBA, 0, 2, 10, 10, 10, 0, 0, 32, 32, GL_UNSIGNED_INT_10_10_10_2, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB10A2, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R32F, 1, UNCOMP_FORMAT, GL_R32F, GL_RED, 0, 0, 32, 0, 0, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R32F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB16, 3, UNCOMP_FORMAT, GL_RGB16, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RG32F, 2, UNCOMP_FORMAT, GL_RG32F, GL_RG, 0, 0, 32, 32, 0, 0, 0, 64, 64, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RG32F, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB16F, 3, UNCOMP_FORMAT, GL_RGB16F_ARB, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB5, 3, UNCOMP_FORMAT, GL_RGB5, GL_RGBA, 0, 0, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB5, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB32F, 3, UNCOMP_FORMAT, GL_RGB32F_ARB, GL_RGB, 0, 0, 32, 32, 32, 0, 0, 32*3, 32*3, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB32F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB5A1, 4, UNCOMP_FORMAT, GL_RGB5_A1, GL_RGBA, 0, 1, 5, 5, 5, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB5A1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8, 3, UNCOMP_FORMAT, GL_RGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB8, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA16, 4, UNCOMP_FORMAT, GL_RGBA16, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB10, 3, UNCOMP_FORMAT, GL_RGB10, GL_RGB, 0, 0, 10, 10, 10, 0, 0, 32, 10*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB10, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB10A2, 4, UNCOMP_FORMAT, GL_RGB10_A2, GL_RGBA, 0, 2, 10, 10, 10, 0, 0, 32, 32, GL_UNSIGNED_INT_10_10_10_2, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB10A2, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGB16, 3, UNCOMP_FORMAT, GL_RGB16, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_UNSIGNED_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB16, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGB16F, 3, UNCOMP_FORMAT, GL_RGB16F_ARB, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 16*3, 16*3, GL_HALF_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32F, 3, UNCOMP_FORMAT, GL_RGB32F_ARB, GL_RGB, 0, 0, 32, 32, 32, 0, 0, 32*3, 32*3, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB32F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8, 4, UNCOMP_FORMAT, GL_RGBA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA8, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16, 4, UNCOMP_FORMAT, GL_RGBA16, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA16, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16F, 4, UNCOMP_FORMAT, GL_RGBA16F_ARB, GL_RGBA, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_HALF_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGBA16F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32F, 4, UNCOMP_FORMAT, GL_RGBA32F_ARB, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB);
+
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16I, 4, UNCOMP_FORMAT, GL_RGBA16I, GL_RGBA_INTEGER, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_SHORT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA16I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16UI, 4, UNCOMP_FORMAT, GL_RGBA16UI, GL_RGBA_INTEGER, 0, 16, 16, 16, 16, 0, 0, 16*4, 16*4, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA16UI, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA32F, 4, UNCOMP_FORMAT, GL_RGBA32F_ARB, GL_RGBA, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGBA32F, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32I, 3, UNCOMP_FORMAT, GL_RGB32I, GL_RGBA_INTEGER, 0, 32, 32, 32, 0, 0, 0, 32*3, 32*3, GL_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB32I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB32UI, 3, UNCOMP_FORMAT, GL_RGB32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 0, 0, 0, 32*3, 32*3, GL_UNSIGNED_INT, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB32UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32I, 4, UNCOMP_FORMAT, GL_RGBA32I, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_INT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA32I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA32UI, 4, UNCOMP_FORMAT, GL_RGBA32UI, GL_RGBA_INTEGER, 0, 32, 32, 32, 32, 0, 0, 32*4, 32*4, GL_UNSIGNED_INT, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA32UI, ImageFormat::COLOR_SPACE_RGB);
-// Unsigned
-DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EXT, GL_RGB, 0, 0, 11, 11, 10, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
-// Unsigned
-DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F, 3, UNCOMP_FORMAT, GL_RGB9_E5_EXT, GL_RGB, 0, 0, 14, 14, 14, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(R11G11B10F, 3, UNCOMP_FORMAT, GL_R11F_G11F_B10F_EXT,GL_RGB, 0, 0, 11, 11, 10, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_R11G11B10F, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB9E5F, 3, UNCOMP_FORMAT, GL_RGB9_E5_EXT, GL_RGB, 0, 0, 14, 14, 14, 0, 0, 32, 32, GL_FLOAT, OPAQUE_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_RGB9E5F, ImageFormat::COLOR_SPACE_RGB);
// The base format for integer formats must be *_INTEGER even though the spec doesn't state this
-DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8I, 3, UNCOMP_FORMAT, GL_RGB8I_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB8I, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8UI, 3, UNCOMP_FORMAT, GL_RGB8UI_EXT, GL_RGB_INTEGER, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGB8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8I, 4, UNCOMP_FORMAT, GL_RGBA8I_EXT, GL_RGBA_INTEGER, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA8I, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI, 4, UNCOMP_FORMAT, GL_RGBA8UI_EXT, GL_RGBA_INTEGER, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INTEGER_FORMAT, ImageFormat::CODE_RGBA8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB8_SNORM, 3, UNCOMP_FORMAT, GL_RGB8_SNORM, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB8_SNORM, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA8UI, 4, UNCOMP_FORMAT, GL_RGBA8UI_EXT, GL_RGBA_INTEGER, 0, 0, 8, 8, 8, 8, 0, 32, 32, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA8UI, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA8_SNORM,4, UNCOMP_FORMAT, GL_RGBA8_SNORM, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 32, GL_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA8_SNORM, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB16_SNORM,3, UNCOMP_FORMAT, GL_RGB16_SNORM, GL_RGB, 0, 0, 16, 16, 16, 0, 0, 64, 64, GL_SHORT, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGB16_SNORM, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA16_SNORM,4,UNCOMP_FORMAT, GL_RGBA16_SNORM, GL_RGB, 0, 16, 16, 16, 16, 0, 0, 64, 64, GL_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_RGBA16_SNORM, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_RGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, OTHER, ImageFormat::CODE_RGB_DXT1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT1, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT1, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT3, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT3, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_RGBA_DXT5, ImageFormat::COLOR_SPACE_RGB);
+DEFINE_TEXTUREFORMAT_METHOD(RGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_RGBA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_RGBA_DXT5, ImageFormat::COLOR_SPACE_RGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGB8, 3, UNCOMP_FORMAT, GL_SRGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGB8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGB8, 3, UNCOMP_FORMAT, GL_SRGB8, GL_RGB, 0, 0, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SRGB8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA8, 4, UNCOMP_FORMAT, GL_SRGB8_ALPHA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA8, 4, UNCOMP_FORMAT, GL_SRGB8_ALPHA8, GL_RGBA, 0, 8, 8, 8, 8, 0, 0, 32, 24, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SRGBA8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SL8, 1, UNCOMP_FORMAT, GL_SLUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SL8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SL8, 1, UNCOMP_FORMAT, GL_SLUMINANCE8, GL_LUMINANCE, 8, 0, 0, 0, 0, 0, 0, 8, 8, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SL8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SLA8, 2, UNCOMP_FORMAT, GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SLA8, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SLA8, 2, UNCOMP_FORMAT, GL_SLUMINANCE8_ALPHA8, GL_LUMINANCE_ALPHA, 8, 8, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_SLA8, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGB_DXT1, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGB_DXT1, 3, COMP_FORMAT, GL_COMPRESSED_SRGB_S3TC_DXT1_EXT, GL_RGB, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, OTHER, ImageFormat::CODE_SRGB_DXT1, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT1, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT1, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 64, 64, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT1, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT3, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT3, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT3, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_SRGBA_DXT5, ImageFormat::COLOR_SPACE_SRGB);
+DEFINE_TEXTUREFORMAT_METHOD(SRGBA_DXT5, 4, COMP_FORMAT, GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT, GL_RGBA, 0, 0, 0, 0, 0, 0, 0, 128, 128, GL_UNSIGNED_BYTE, CLEAR_FORMAT, OTHER, ImageFormat::CODE_SRGBA_DXT5, ImageFormat::COLOR_SPACE_SRGB);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH16, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 16, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH16, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH16, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT16_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 16, 0, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH16, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH24, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 24, 0, 32, 24, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH24, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT24_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 24, 0, 32, 24, GL_UNSIGNED_INT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH24, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH32, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH32, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH32, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH32, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH32F, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOAT_FORMAT, ImageFormat::CODE_DEPTH32F, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH32F, 1, UNCOMP_FORMAT, GL_DEPTH_COMPONENT32_ARB, GL_DEPTH_COMPONENT, 0, 0, 0, 0, 0, 32, 0, 32, 32, GL_FLOAT, CLEAR_FORMAT, FLOATING_POINT_FORMAT, ImageFormat::CODE_DEPTH32F, ImageFormat::COLOR_SPACE_NONE);
// These formats are for use with Renderbuffers only!
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL1, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 1, 1, 1, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL1, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL1, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX1_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 1, 1, 1, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL1, ImageFormat::COLOR_SPACE_NONE);
+
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL4, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL4, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL4, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX4_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 4, 4, 4, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL4, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL8, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 8, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL8, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX8_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 8, 8, 8, GL_UNSIGNED_BYTE, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(STENCIL16, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX16_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_STENCIL16, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(STENCIL16, 1, UNCOMP_FORMAT, GL_STENCIL_INDEX16_EXT, GL_STENCIL_INDEX, 0, 0, 0, 0, 0, 0, 16, 16, 16, GL_UNSIGNED_SHORT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_STENCIL16, ImageFormat::COLOR_SPACE_NONE);
+DEFINE_TEXTUREFORMAT_METHOD(DEPTH24_STENCIL8, 2, UNCOMP_FORMAT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT,0, 0, 0, 0, 0, 24, 8, 32, 32, GL_UNSIGNED_INT_24_8, CLEAR_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_DEPTH24_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(DEPTH24_STENCIL8, 2, UNCOMP_FORMAT, GL_DEPTH24_STENCIL8_EXT, GL_DEPTH_STENCIL_EXT,0, 0, 0, 0, 0, 24, 8, 32, 32, GL_UNSIGNED_INT, CLEAR_FORMAT, INT_FORMAT, ImageFormat::CODE_DEPTH24_STENCIL8, ImageFormat::COLOR_SPACE_NONE);
-DEFINE_TEXTUREFORMAT_METHOD(YUV420_PLANAR, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 12, 12, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV420_PLANAR, ImageFormat::COLOR_SPACE_YUV);
-DEFINE_TEXTUREFORMAT_METHOD(YUV422, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV422, ImageFormat::COLOR_SPACE_YUV);
-DEFINE_TEXTUREFORMAT_METHOD(YUV444, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 24, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, INT_FORMAT, ImageFormat::CODE_YUV444, ImageFormat::COLOR_SPACE_YUV);
+// TODO: Find out if these are acutally NFP, not integer, formats.
+DEFINE_TEXTUREFORMAT_METHOD(YUV420_PLANAR, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 12, 12, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV420_PLANAR, ImageFormat::COLOR_SPACE_YUV);
+DEFINE_TEXTUREFORMAT_METHOD(YUV422, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 16, 16, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV422, ImageFormat::COLOR_SPACE_YUV);
+DEFINE_TEXTUREFORMAT_METHOD(YUV444, 3, UNCOMP_FORMAT, GL_NONE, GL_NONE, 0, 0, 0, 0, 0, 0, 0, 24, 24, GL_UNSIGNED_BYTE, OPAQUE_FORMAT, NORMALIZED_FIXED_POINT_FORMAT, ImageFormat::CODE_YUV444, ImageFormat::COLOR_SPACE_YUV);
}
diff --git a/dep/g3dlite/source/ImageFormat_convert.cpp b/dep/g3dlite/source/ImageFormat_convert.cpp
index ecefe6319c7..69b9c71aeca 100644
--- a/dep/g3dlite/source/ImageFormat_convert.cpp
+++ b/dep/g3dlite/source/ImageFormat_convert.cpp
@@ -1,7 +1,7 @@
#include "G3D/ImageFormat.h"
-#include "G3D/Color1uint8.h"
-#include "G3D/Color3uint8.h"
-#include "G3D/Color4uint8.h"
+#include "G3D/Color1unorm8.h"
+#include "G3D/Color3unorm8.h"
+#include "G3D/Color4unorm8.h"
#include "G3D/Color1.h"
#include "G3D/Color3.h"
#include "G3D/Color4.h"
@@ -212,8 +212,8 @@ bool ImageFormat::convert(const Array<const void*>& srcBytes, int srcWidth, int
static void l8_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
(void)bayerAlg;
(void)dstRowPadBits;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -230,7 +230,7 @@ static void l8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int src
static void l32f_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
int srcIndex = 0;
int dstByteOffset = 0;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const float* src = static_cast<const float*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -239,19 +239,18 @@ static void l32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int s
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
- float s = src[srcIndex];
-
- uint8 c = iMin(255, iFloor(s * 256));
- d = Color3uint8(c, c, c);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
+ const float s = src[srcIndex];
+ const unorm8 c(s);
+ d = Color3unorm8(c, c, c);
}
}
}
// RGB8 ->
static void rgb8_to_rgba8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -261,14 +260,14 @@ static void rgb8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int
dst[i4 + 0] = src[i3 + 0];
dst[i4 + 1] = src[i3 + 1];
dst[i4 + 2] = src[i3 + 2];
- dst[i4 + 3] = 255;
+ dst[i4 + 3] = unorm8::one();
}
}
}
static void rgb8_to_bgr8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -287,14 +286,14 @@ static void rgb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
dstIndex = srcWidth * (srcHeight - 1 - y);
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) {
- const Color3uint8& s = *reinterpret_cast<const Color3uint8*>(src + srcByteOffset);
+ const Color3unorm8& s = *reinterpret_cast<const Color3unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(Color3(s), 1.0f);
}
srcByteOffset += srcRowPadBytes;
@@ -303,8 +302,8 @@ static void rgb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
// BGR8 ->
static void bgr8_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -317,8 +316,8 @@ static void bgr8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int s
}
static void bgr8_to_rgba8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -328,7 +327,7 @@ static void bgr8_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, int
dst[i4 + 0] = src[i3 + 2];
dst[i4 + 1] = src[i3 + 1];
dst[i4 + 2] = src[i3 + 0];
- dst[i4 + 3] = 255;
+ dst[i4 + 3] = unorm8::one();
}
}
}
@@ -340,7 +339,7 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -348,7 +347,7 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 3) {
- const Color3uint8& s = *reinterpret_cast<const Color3uint8*>(src + srcByteOffset);
+ const Color3unorm8& s = *reinterpret_cast<const Color3unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(Color3(s).bgr(), 1.0f);
}
srcByteOffset += srcRowPadBytes;
@@ -357,8 +356,8 @@ static void bgr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, in
// RGBA8 ->
static void rgba8_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -373,8 +372,8 @@ static void rgba8_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
}
static void rgba8_to_bgr8(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, ImageFormat::BayerAlgorithm bayerAlg) {
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
int i = (invertY) ? ((srcHeight-1-y) * srcWidth +x) : (y * srcWidth + x);
@@ -395,7 +394,7 @@ static void rgba8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, i
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -403,7 +402,7 @@ static void rgba8_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth, i
}
for (int x = 0; x < srcWidth; ++x, ++dstIndex, srcByteOffset += 4) {
- const Color4uint8& s = *reinterpret_cast<const Color4uint8*>(src + srcByteOffset);
+ const Color4unorm8& s = *reinterpret_cast<const Color4unorm8*>(src + srcByteOffset);
dst[dstIndex] = Color4(s);
}
srcByteOffset += srcRowPadBytes;
@@ -418,7 +417,7 @@ static void rgb32f_to_rgba32f(const Array<const void*>& srcBytes, int srcWidth,
int srcByteOffset = 0;
int srcRowPadBytes = srcRowPadBits / 8;
Color4* dst = static_cast<Color4*>(dstBytes[0]);
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
if (invertY) {
@@ -440,7 +439,7 @@ static void rgba32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, in
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -449,10 +448,10 @@ static void rgba32f_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color3uint8(s.rgb());
+ d = Color3unorm8(s.rgb());
}
dstByteOffset += dstRowPadBytes;
}
@@ -464,7 +463,7 @@ static void rgba32f_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, i
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -472,10 +471,10 @@ static void rgba32f_to_rgba8(const Array<const void*>& srcBytes, int srcWidth, i
srcIndex = srcWidth * (srcHeight - 1 - y);
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 4) {
- Color4uint8& d = *reinterpret_cast<Color4uint8*>(dst + dstByteOffset);
+ Color4unorm8& d = *reinterpret_cast<Color4unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color4uint8(s);
+ d = Color4unorm8(s);
}
dstByteOffset += dstRowPadBytes;
}
@@ -487,7 +486,7 @@ static void rgba32f_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, in
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -496,10 +495,10 @@ static void rgba32f_to_bgr8(const Array<const void*>& srcBytes, int srcWidth, in
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3) {
- Color3uint8& d = *reinterpret_cast<Color3uint8*>(dst + dstByteOffset);
+ Color3unorm8& d = *reinterpret_cast<Color3unorm8*>(dst + dstByteOffset);
const Color4& s = src[srcIndex];
- d = Color3uint8(s.rgb()).bgr();
+ d = Color3unorm8(s.rgb()).bgr();
}
dstByteOffset += dstRowPadBytes;
}
@@ -511,7 +510,7 @@ static void rgba32f_to_rgb32f(const Array<const void*>& srcBytes, int srcWidth,
int srcIndex = 0;
int dstByteOffset = 0;
int dstRowPadBytes = dstRowPadBits / 8;
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
const Color4* src = static_cast<const Color4*>(srcBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
@@ -520,7 +519,7 @@ static void rgba32f_to_rgb32f(const Array<const void*>& srcBytes, int srcWidth,
}
for (int x = 0; x < srcWidth; ++x, ++srcIndex, dstByteOffset += 3 * sizeof(float)) {
Color3& d = *reinterpret_cast<Color3*>(dst + dstByteOffset);
- const Color4& s = src[srcIndex];
+ const Color4& s = src[srcIndex];
d = s.rgb();
}
dstByteOffset += dstRowPadBytes;
@@ -545,19 +544,19 @@ static uint32 blendPixels(uint32 pixel1, uint32 pixel2) {
return ((rb & rbMask) | (ag & agMask));
}
-#define PIXEL_RGB8_TO_YUV_Y(r, g, b) static_cast<uint8>(iClamp(((66 * r + 129 * g + 25 * b + 128) >> 8) + 16, 0, 255))
-#define PIXEL_RGB8_TO_YUV_U(r, g, b) static_cast<uint8>(iClamp(((-38 * r - 74 * g + 112 * b + 128) >> 8) + 128, 0, 255))
-#define PIXEL_RGB8_TO_YUV_V(r, g, b) static_cast<uint8>(iClamp(((112 * r - 94 * g - 18 * b + 128) >> 8) + 128, 0, 255))
+#define PIXEL_RGB8_TO_YUV_Y(r, g, b) unorm8::fromBits(iClamp(((66 * r.bits() + 129 * g.bits() + 25 * b.bits() + 128) >> 8) + 16, 0, 255))
+#define PIXEL_RGB8_TO_YUV_U(r, g, b) unorm8::fromBits(iClamp(((-38 * r.bits() - 74 * g.bits() + 112 * b.bits() + 128) >> 8) + 128, 0, 255))
+#define PIXEL_RGB8_TO_YUV_V(r, g, b) unorm8::fromBits(iClamp(((112 * r.bits() - 94 * g.bits() - 18 * b.bits() + 128) >> 8) + 128, 0, 255))
static void rgb8_to_yuv420p(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, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- uint8* dstY = static_cast<uint8*>(dstBytes[0]);
- uint8* dstU = static_cast<uint8*>(dstBytes[1]);
- uint8* dstV = static_cast<uint8*>(dstBytes[2]);
+ unorm8* dstY = static_cast<unorm8*>(dstBytes[0]);
+ unorm8* dstU = static_cast<unorm8*>(dstBytes[1]);
+ unorm8* dstV = static_cast<unorm8*>(dstBytes[2]);
for (int y = 0; y < srcHeight; y += 2) {
for (int x = 0; x < srcWidth; x += 2) {
@@ -578,7 +577,7 @@ static void rgb8_to_yuv420p(const Array<const void*>& srcBytes, int srcWidth, in
dstY[yIndex + 1] = PIXEL_RGB8_TO_YUV_Y(src[srcPixelOffset3].r, src[srcPixelOffset3].g, src[srcPixelOffset3].b);
uint32 blendedPixel = blendPixels(src[srcPixelOffset0].asUInt32(), src[srcPixelOffset2].asUInt32());
- Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel);
+ Color3unorm8 uvSrcColor = Color3unorm8::fromARGB(blendedPixel);
int uvIndex = y / 2 * srcWidth / 2 + x / 2;
dstU[uvIndex] = PIXEL_RGB8_TO_YUV_U(uvSrcColor.r, uvSrcColor.g, uvSrcColor.b);
@@ -591,9 +590,9 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- uint8* dst = static_cast<uint8*>(dstBytes[0]);
+ unorm8* dst = static_cast<unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
@@ -603,7 +602,7 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
int dstIndex = srcIndex * 2;
uint32 blendedPixel = blendPixels(src[srcIndex].asUInt32(), src[srcIndex + 1].asUInt32());
- Color3uint8 uvSrcColor = Color3uint8::fromARGB(blendedPixel);
+ Color3unorm8 uvSrcColor = Color3unorm8::fromARGB(blendedPixel);
dst[dstIndex] = PIXEL_RGB8_TO_YUV_Y(src[srcIndex].r, src[srcIndex].g, src[srcIndex].b);
@@ -620,18 +619,18 @@ static void rgb8_to_yuv422(const Array<const void*>& srcBytes, int srcWidth, int
static void rgb8_to_yuv444(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, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
// convert 1-pixels at a time
int index = y * srcWidth + x;
- uint8 y = PIXEL_RGB8_TO_YUV_Y(src[index].r, src[index].g, src[index].b);
- uint8 u = PIXEL_RGB8_TO_YUV_U(src[index].r, src[index].g, src[index].b);
- uint8 v = PIXEL_RGB8_TO_YUV_V(src[index].r, src[index].g, src[index].b);
+ unorm8 y = PIXEL_RGB8_TO_YUV_Y(src[index].r, src[index].g, src[index].b);
+ unorm8 u = PIXEL_RGB8_TO_YUV_U(src[index].r, src[index].g, src[index].b);
+ unorm8 v = PIXEL_RGB8_TO_YUV_V(src[index].r, src[index].g, src[index].b);
dst[index].r = y;
dst[index].g = u;
@@ -641,25 +640,25 @@ static void rgb8_to_yuv444(const Array<const void*>& srcBytes, int srcWidth, int
}
-#define PIXEL_YUV_TO_RGB8_R(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) + 409 * (v - 128) + 128) >> 8, 0, 255))
-#define PIXEL_YUV_TO_RGB8_G(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) - 100 * (u - 128) - 208 * (v - 128) + 128) >> 8, 0, 255))
-#define PIXEL_YUV_TO_RGB8_B(y, u, v) static_cast<uint8>(iClamp((298 * (y - 16) + 516 * (u - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_R(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) + 409 * (v.bits() - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_G(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) - 100 * (u.bits() - 128) - 208 * (v.bits() - 128) + 128) >> 8, 0, 255))
+#define PIXEL_YUV_TO_RGB8_B(y, u, v) unorm8::fromBits(iClamp((298 * (y.bits() - 16) + 516 * (u.bits() - 128) + 128) >> 8, 0, 255))
static void yuv420p_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0) && (srcHeight % 2 == 0), "Source width and height must be a multiple of two");
- const uint8* srcY = static_cast<const uint8*>(srcBytes[0]);
- const uint8* srcU = static_cast<const uint8*>(srcBytes[1]);
- const uint8* srcV = static_cast<const uint8*>(srcBytes[2]);
+ const unorm8* srcY = static_cast<const unorm8*>(srcBytes[0]);
+ const unorm8* srcU = static_cast<const unorm8*>(srcBytes[1]);
+ const unorm8* srcV = static_cast<const unorm8*>(srcBytes[2]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
// convert to two rgb pixels in a row
- Color3uint8* rgb = &dst[y * srcWidth + x];
+ Color3unorm8* rgb = &dst[y * srcWidth + x];
int yOffset = y * srcWidth + x;
int uvOffset = y / 2 * srcWidth / 2 + x / 2;
@@ -680,21 +679,21 @@ static void yuv422_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
debugAssertM((srcWidth % 2 == 0), "Source width must be a multiple of two");
- const uint8* src = static_cast<const uint8*>(srcBytes[0]);
+ const unorm8* src = static_cast<const unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; x += 2) {
// convert to two rgb pixels in a row
- Color3uint8* rgb = &dst[y * srcWidth + x];
+ Color3unorm8* rgb = &dst[y * srcWidth + x];
- int srcIndex = (y * srcWidth + x) * 2;
- uint8 y = src[srcIndex];
- uint8 u = src[srcIndex + 1];
- uint8 y2 = src[srcIndex + 2];
- uint8 v = src[srcIndex + 3];
+ const int srcIndex = (y * srcWidth + x) * 2;
+ const unorm8 y = src[srcIndex];
+ const unorm8 u = src[srcIndex + 1];
+ const unorm8 y2 = src[srcIndex + 2];
+ const unorm8 v = src[srcIndex + 3];
rgb->r = PIXEL_YUV_TO_RGB8_R(y, u, v);
rgb->g = PIXEL_YUV_TO_RGB8_G(y, u, v);
@@ -711,20 +710,21 @@ static void yuv422_to_rgb8(const Array<const void*>& srcBytes, int srcWidth, int
static void yuv444_to_rgb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
debugAssertM(srcRowPadBits == 0, "Source row padding must be 0 for this format");
- const Color3uint8* src = static_cast<const Color3uint8*>(srcBytes[0]);
+ const Color3unorm8* src = static_cast<const Color3unorm8*>(srcBytes[0]);
- Color3uint8* dst = static_cast<Color3uint8*>(dstBytes[0]);
+ Color3unorm8* dst = static_cast<Color3unorm8*>(dstBytes[0]);
for (int y = 0; y < srcHeight; ++y) {
for (int x = 0; x < srcWidth; ++x) {
// convert to one rgb pixels at a time
- int index = y * srcWidth + x;
- Color3uint8* rgb = &dst[index];
-
- rgb->r = PIXEL_YUV_TO_RGB8_R(src[index].r, src[index].g, src[index].b);
- rgb->g = PIXEL_YUV_TO_RGB8_G(src[index].r, src[index].g, src[index].b);
- rgb->b = PIXEL_YUV_TO_RGB8_B(src[index].r, src[index].g, src[index].b);
+ const int index = y * srcWidth + x;
+ const Color3unorm8 s = src[index];
+
+ Color3unorm8& rgb = dst[index];
+ rgb.r = PIXEL_YUV_TO_RGB8_R(s.r, s.g, s.b);
+ rgb.g = PIXEL_YUV_TO_RGB8_G(s.r, s.g, s.b);
+ rgb.b = PIXEL_YUV_TO_RGB8_B(s.r, s.g, s.b);
}
}
}
@@ -799,12 +799,12 @@ static const float R_BGB[5][5] =
/** Applies a 5x5 filter to monochrome image I (wrapping at the boundaries) */
-static uint8 applyFilter(const uint8* I,
- int x,
- int y,
- int w,
- int h,
- const float filter[5][5]) {
+static unorm8 applyFilter(const unorm8* I,
+ int x,
+ int y,
+ int w,
+ int h,
+ const float filter[5][5]) {
debugAssert(isEven(w));
debugAssert(isEven(h));
@@ -813,24 +813,24 @@ static uint8 applyFilter(const uint8* I,
float denom = 0.0f;
for (int dy = 0; dy < 5; ++dy) {
- int offset = ((y + dy + h - 2) % h) * w;
+ int offset = ((y + dy + h - 2) % h) * w;
- for (int dx = 0; dx < 5; ++dx) {
- float f = filter[dy][dx];
- sum += f * I[((x + dx + w - 2) % w) + offset];
- denom += f;
- }
+ for (int dx = 0; dx < 5; ++dx) {
+ float f = filter[dy][dx];
+ sum += f * (float)I[((x + dx + w - 2) % w) + offset];
+ denom += f;
+ }
}
- return (uint8)iClamp(iRound(sum / denom), 0, 255);
+ return unorm8(sum / denom);
}
/** Helper method for Bayer grbg and bggr --> rgb8 */
-static void swapRedAndBlue(int N, Color3uint8* out) {
+static void swapRedAndBlue(int N, Color3unorm8* out) {
for (int i = N - 1; i >= 0; --i) {
- uint8 tmp = out[i].r;
- out[i].r = out[i].b;
- out[i].b = tmp;
+ unorm8 tmp = out[i].r;
+ out[i].r = out[i].b;
+ out[i].b = tmp;
}
}
@@ -840,149 +840,149 @@ static void swapRedAndBlue(int N, Color3uint8* out) {
// rgb8 --> bayer helpers
// =====================================================================
static void rgb8_to_bayer_rggb8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Top left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
- // Top right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
- }
+ // Top right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
+ }
- // Bottom row pixels
- for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ // Bottom row pixels
+ for (int y = 1; y < h - 1; y += 2) {
+ int offset = y * w;
- // Bottom left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Bottom right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Bottom right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
}
}
static void rgb8_to_bayer_grbg8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Top right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Top right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
}
// Bottom row pixels
for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Bottom left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
- // Bottom right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
}
static void rgb8_to_bayer_bggr8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for (int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for (int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Top left pixels
+ for (int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
- // Top right pixels
- for (int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top right pixels
+ for (int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
// Bottom row pixels
for (int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Bottom right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Bottom right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
}
}
static void rgb8_to_bayer_gbrg8(const int w, const int h,
- const uint8* src, uint8* dst) {
- Color3uint8* srcColor = (Color3uint8*)src;
- Color1uint8* dstColor = (Color1uint8*)dst;
+ const unorm8* src, unorm8* dst) {
+ Color3unorm8* srcColor = (Color3unorm8*)src;
+ Color1unorm8* dstColor = (Color1unorm8*)dst;
// Top row pixels
for(int y = 0; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Top left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Top left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
- // Top right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].b);
- }
+ // Top right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].b);
+ }
}
// Bottom row pixels
for(int y = 1; y < h - 1; y += 2) {
- int offset = y * w;
+ int offset = y * w;
- // Bottom left pixels
- for(int x = 0; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].r);
- }
+ // Bottom left pixels
+ for(int x = 0; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].r);
+ }
- // Bottom right pixels
- for(int x = 1; x < w - 1; x += 2) {
- dstColor[x + offset] = Color1(srcColor[x + offset].g);
- }
+ // Bottom right pixels
+ for(int x = 1; x < w - 1; x += 2) {
+ dstColor[x + offset] = Color1unorm8(srcColor[x + offset].g);
+ }
}
}
@@ -991,40 +991,40 @@ static void rgb8_to_bayer_gbrg8(const int w, const int h,
// =====================================================================
static void rgba32f_to_bayer_rggb8(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_rggb8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_rggb8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_gbrg8(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_grbg8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_grbg8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_grbg8(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_gbrg8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_gbrg8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
static void rgba32f_to_bayer_bggr8(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
rgba32f_to_rgb8(srcBytes, srcWidth, srcHeight, ImageFormat::RGBA32F(), 0, tmp, ImageFormat::RGB8(), 0, invertY, bayerAlg);
- rgb8_to_bayer_bggr8(srcWidth, srcHeight, static_cast<uint8*>(tmp[0]), static_cast<uint8*>(dstBytes[0]));
+ rgb8_to_bayer_bggr8(srcWidth, srcHeight, static_cast<unorm8*>(tmp[0]), static_cast<unorm8*>(dstBytes[0]));
System::free(tmp[0]);
}
@@ -1035,109 +1035,109 @@ static void rgba32f_to_bayer_bggr8(const Array<const void*>& srcBytes, int srcWi
// bayer --> rgb8 helpers
// =====================================================================
static void bayer_rggb8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
debugAssert(in != _out);
- Color3uint8* out = (Color3uint8*)_out;
+ Color3unorm8* out = (Color3unorm8*)_out;
for (int y = 0; y < h; ++y) {
- // Row beginning in the input array.
- int offset = y * w;
-
- // RG row
- for (int x = 0; x < w; ++x, ++out) {
- // R pixel
- {
- out->r = in[x + offset];
- out->g = applyFilter(in, x, y, w, h, G_GRR);
- out->b = applyFilter(in, x, y, w, h, B_GRR);
- }
- ++x; ++out;
-
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_GRG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_GRG);
- }
- }
-
- ++y;
- offset += w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // RG row
+ for (int x = 0; x < w; ++x, ++out) {
+ // R pixel
+ {
+ out->r = in[x + offset];
+ out->g = applyFilter(in, x, y, w, h, G_GRR);
+ out->b = applyFilter(in, x, y, w, h, B_GRR);
+ }
+ ++x; ++out;
+
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_GRG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_GRG);
+ }
+ }
+
+ ++y;
+ offset += w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
}
}
static void bayer_gbrg8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
debugAssert(in != _out);
- Color3uint8* out = (Color3uint8*)_out;
+ Color3unorm8* out = (Color3unorm8*)_out;
for (int y = 0; y < h; ++y) {
- // Row beginning in the input array.
- int offset = y * w;
-
- // GB row
- for (int x = 0; x < w; ++x, ++out) {
- // G pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGG);
- out->g = in[x + offset];
- out->b = applyFilter(in, x, y, w, h, B_BGG);
- }
- ++x; ++out;
-
- // B pixel
- {
- out->r = applyFilter(in, x, y, w, h, R_BGB);
- out->g = applyFilter(in, x, y, w, h, G_BGB);
- out->b = in[x + offset];
- }
- }
+ // Row beginning in the input array.
+ int offset = y * w;
+
+ // GB row
+ for (int x = 0; x < w; ++x, ++out) {
+ // G pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGG);
+ out->g = in[x + offset];
+ out->b = applyFilter(in, x, y, w, h, B_BGG);
+ }
+ ++x; ++out;
+
+ // B pixel
+ {
+ out->r = applyFilter(in, x, y, w, h, R_BGB);
+ out->g = applyFilter(in, x, y, w, h, G_BGB);
+ out->b = in[x + offset];
+ }
+ }
}
}
static void bayer_grbg8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
// Run the equivalent function for red
bayer_gbrg8_to_rgb8_mhc(w, h, in, _out);
// Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
+ swapRedAndBlue(w * h, (Color3unorm8*)_out);
}
static void bayer_bggr8_to_rgb8_mhc(int w, int h,
- const uint8* in, uint8* _out) {
+ const unorm8* in, unorm8* _out) {
// Run the equivalent function for red
bayer_rggb8_to_rgb8_mhc(w, h, in, _out);
// Now swap red and blue
- swapRedAndBlue(w * h, (Color3uint8*)_out);
+ swapRedAndBlue(w * h, (Color3unorm8*)_out);
}
// =====================================================================
@@ -1145,9 +1145,9 @@ static void bayer_bggr8_to_rgb8_mhc(int w, int h,
// =====================================================================
static void bayer_rggb8_to_rgba32f(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_rggb8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_rggb8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1155,9 +1155,9 @@ static void bayer_rggb8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_gbrg8_to_rgba32f(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_grbg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_grbg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1165,9 +1165,9 @@ static void bayer_gbrg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_grbg8_to_rgba32f(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_gbrg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_gbrg8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1175,9 +1175,9 @@ static void bayer_grbg8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
static void bayer_bggr8_to_rgba32f(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, ImageFormat::BayerAlgorithm bayerAlg) {
Array<void*> tmp;
- tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3uint8)));
+ tmp.append(System::malloc(srcWidth * srcHeight * sizeof(Color3unorm8)));
- bayer_bggr8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const uint8*>(srcBytes[0]), static_cast<uint8*>(tmp[0]));
+ bayer_bggr8_to_rgb8_mhc(srcWidth, srcHeight, static_cast<const unorm8*>(srcBytes[0]), static_cast<unorm8*>(tmp[0]));
rgb8_to_rgba32f(reinterpret_cast<Array<const void*>&>(tmp), srcWidth, srcHeight, ImageFormat::RGB8(), 0, dstBytes, ImageFormat::RGBA32F(), 0, invertY, bayerAlg);
System::free(tmp[0]);
@@ -1198,106 +1198,106 @@ static void bayer_bggr8_to_rgba32f(const Array<const void*>& srcBytes, int srcWi
// // =====================================================================
// static void bayer_rggb8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// debugAssert(in != _out);
-// Color3uint8* out = (Color3uint8*)_out;
+// Color3unorm8* out = (Color3unorm8*)_out;
// for (int y = 0; y < h; ++y) {
-// // Row beginning in the input array.
-// int offset = y * w;
-
-// // RG row
-// for (int x = 0; x < w; ++x, ++out) {
-// // R pixel
-// {
-// out->b = in[x + offset];
-// out->g = applyFilter(in, x, y, w, h, G_GRR);
-// out->r = applyFilter(in, x, y, w, h, B_GRR);
-// }
-// ++x; ++out;
-
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_GRG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_GRG);
-// }
-// }
-
-// ++y;
-// offset += w;
-
-// // GB row
-// for (int x = 0; x < w; ++x, ++out) {
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_BGG);
-// }
-// ++x; ++out;
-
-// // B pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGB);
-// out->g = applyFilter(in, x, y, w, h, G_BGB);
-// out->r = in[x + offset];
-// }
-// }
+// // Row beginning in the input array.
+// int offset = y * w;
+
+// // RG row
+// for (int x = 0; x < w; ++x, ++out) {
+// // R pixel
+// {
+// out->b = in[x + offset];
+// out->g = applyFilter(in, x, y, w, h, G_GRR);
+// out->r = applyFilter(in, x, y, w, h, B_GRR);
+// }
+// ++x; ++out;
+
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_GRG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_GRG);
+// }
+// }
+
+// ++y;
+// offset += w;
+
+// // GB row
+// for (int x = 0; x < w; ++x, ++out) {
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_BGG);
+// }
+// ++x; ++out;
+
+// // B pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGB);
+// out->g = applyFilter(in, x, y, w, h, G_BGB);
+// out->r = in[x + offset];
+// }
+// }
// }
// }
// static void bayer_gbrg8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// debugAssert(in != _out);
-// Color3uint8* out = (Color3uint8*)_out;
+// Color3unorm8* out = (Color3unorm8*)_out;
// for (int y = 0; y < h; ++y) {
-// // Row beginning in the input array.
-// int offset = y * w;
-
-// // GB row
-// for (int x = 0; x < srcWidth; ++x, ++out) {
-// // G pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGG);
-// out->g = in[x + offset];
-// out->r = applyFilter(in, x, y, w, h, B_BGG);
-// }
-// ++x; ++out;
-
-// // B pixel
-// {
-// out->b = applyFilter(in, x, y, w, h, R_BGB);
-// out->g = applyFilter(in, x, y, w, h, G_BGB);
-// out->r = in[x + offset];
-// }
-// }
+// // Row beginning in the input array.
+// int offset = y * w;
+
+// // GB row
+// for (int x = 0; x < srcWidth; ++x, ++out) {
+// // G pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGG);
+// out->g = in[x + offset];
+// out->r = applyFilter(in, x, y, w, h, B_BGG);
+// }
+// ++x; ++out;
+
+// // B pixel
+// {
+// out->b = applyFilter(in, x, y, w, h, R_BGB);
+// out->g = applyFilter(in, x, y, w, h, G_BGB);
+// out->r = in[x + offset];
+// }
+// }
// }
// }
// static void bayer_grbg8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// // Run the equivalent function for red
// bayer_gbrg8_to_bgr8_mhc(w, h, in, _out);
// // Now swap red and blue
-// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out);
+// swapRedAndBlue(srcWidth * h, (Color3unorm8*)_out);
// }
// static void bayer_bggr8_to_bgr8_mhc(int w, int h,
-// const uint8* in, uint8* _out) {
+// const unorm8* in, unorm8* _out) {
// // Run the equivalent function for red
// bayer_rggb8_to_bgr8_mhc(w, h, in, _out);
// // Now swap red and blue
-// swapRedAndBlue(srcWidth * h, (Color3uint8*)_out);
+// swapRedAndBlue(srcWidth * h, (Color3unorm8*)_out);
// }
diff --git a/dep/g3dlite/source/Intersect.cpp b/dep/g3dlite/source/Intersect.cpp
index 929a2e4e670..06c9630c170 100644
--- a/dep/g3dlite/source/Intersect.cpp
+++ b/dep/g3dlite/source/Intersect.cpp
@@ -1,23 +1,23 @@
/**
- @file Intersect.cpp
-
- @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
- */
+@file Intersect.cpp
+
+@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
+*/
#include "G3D/Intersect.h"
namespace G3D {
#ifdef _MSC_VER
-// Turn on fast floating-point optimizations
+ // Turn on fast floating-point optimizations
#pragma float_control( push )
#pragma fp_contract( on )
#pragma fenv_access( off )
@@ -28,816 +28,821 @@ namespace G3D {
bool __fastcall Intersect::rayAABox(const Ray& ray, const AABox& box) {
switch (ray.classification) {
case Ray::MMM:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MMP:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MPM:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::MPP:
-
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
-
- return true;
-
- case Ray::PMM:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PMP:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PPM:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
-
- return true;
-
- case Ray::PPP:
-
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- return true;
-
- case Ray::OMM:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- )
- return false;
-
- return true;
- case Ray::OMP:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- )
- return false;
-
- return true;
-
- case Ray::OPM:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- )
- return false;
-
- return true;
-
- case Ray::OPP:
-
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- )
- return false;
-
- return true;
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MMP:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MPM:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::MPP:
+
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PMM:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PMP:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
+
+ case Ray::PPM:
+
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MOM:
+ case Ray::PPP:
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ } else
+ return true;
- return true;
+ case Ray::OMM:
- case Ray::MOP:
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
- )
- return false;
+ case Ray::OMP:
- return true;
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::POM:
+ case Ray::OPM:
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::OPP:
- case Ray::POP:
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
- )
- return false;
+ case Ray::MOM:
- return true;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MMO:
+ case Ray::MOP:
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- )
- return false;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::POM:
- case Ray::MPO:
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- )
- return false;
+ case Ray::POP:
- return true;
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::PMO:
+ case Ray::MMO:
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::MPO:
- case Ray::PPO:
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- )
- return false;
+ case Ray::PMO:
- return true;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ )
+ return false;
+ else
+ return true;
- case Ray::MOO:
+ case Ray::PPO:
- if((ray.m_origin.x < box.lo.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ )
+ return false;
+ else
+ return true;
- return true;
+ case Ray::MOO:
- case Ray::POO:
+ if((ray.m_origin.x < box.lo.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- if((ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ case Ray::POO:
- return true;
+ if((ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OMO:
+ case Ray::OMO:
- if((ray.m_origin.y < box.lo.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.y < box.lo.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OPO:
+ case Ray::OPO:
- if((ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- )
- return false;
+ if((ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ )
+ return false;
+ else
+ return true;
- case Ray::OOM:
+ case Ray::OOM:
- if((ray.m_origin.z < box.lo.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- )
- return false;
+ if((ray.m_origin.z < box.lo.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ )
+ return false;
+ else
+ return true;
- case Ray::OOP:
+ case Ray::OOP:
- if((ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- )
- return false;
+ if((ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ )
+ return false;
+ else
+ return true;
- return true;
-
- }
+ }
- return false;
+ return false;
}
bool __fastcall Intersect::rayAABox(const Ray& ray, const AABox& box, float& time) {
- switch (ray.classification) {
- case Ray::MMM:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- // compute the intersection distance
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MMP:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MPM:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MPP:
- {
- if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PMM:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::PMP:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PPM:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::PPP:
- {
- if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OMM:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OMP:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
- || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OPM:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
- || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)) {
- return false;
- }
-
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::OPP:
- {
- if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
- || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
- || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)) {
- return false;
- }
-
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::MOM:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::MOP:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::POM:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
- || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
- || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
-
- case Ray::POP:
- {
- if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
- || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
- || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- if (t2 > time) {
- time = t2;
- }
-
- return true;
- }
-
- case Ray::MMO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
- case Ray::MPO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)) {
- return false;
- }
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
-
- case Ray::PMO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
- || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
- || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
- case Ray::PPO:
- {
- if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
- || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
- || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)) {
- return false;
- }
-
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- if (t1 > time) {
- time = t1;
- }
-
- return true;
- }
-
-
- case Ray::MOO:
- {
- if((ray.m_origin.x < box.lo.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+ switch (ray.classification) {
+ case Ray::MMM:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ // compute the intersection distance
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MMP:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MPM:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MPP:
+ {
+ if ((ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PMM:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::PMP:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PPM:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::PPP:
+ {
+ if ((ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OMM:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.hi.z + ray.c_yz > 0)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OMP:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.hi.y + ray.c_zy > 0)
+ || (ray.kbyj * box.lo.y - box.lo.z + ray.c_yz < 0)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OPM:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z < box.lo.z)
+ || (ray.jbyk * box.lo.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.hi.z + ray.c_yz > 0)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::OPP:
+ {
+ if((ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y > box.hi.y) || (ray.m_origin.z > box.hi.z)
+ || (ray.jbyk * box.hi.z - box.lo.y + ray.c_zy < 0)
+ || (ray.kbyj * box.hi.y - box.lo.z + ray.c_yz < 0)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOM:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.lo.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOP:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.lo.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.hi.x + ray.c_zx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::POM:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z < box.lo.z)
+ || (ray.kbyi * box.hi.x - box.hi.z + ray.c_xz > 0)
+ || (ray.ibyk * box.lo.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+
+ case Ray::POP:
+ {
+ if((ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.z > box.hi.z)
+ || (ray.kbyi * box.hi.x - box.lo.z + ray.c_xz < 0)
+ || (ray.ibyk * box.hi.z - box.lo.x + ray.c_zx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t2 = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ if (t2 > time) {
+ time = t2;
+ }
+
+ return true;
+ }
+
+ case Ray::MMO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.lo.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.hi.x + ray.c_yx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+ case Ray::MPO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.lo.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.hi.x + ray.c_yx > 0)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
}
-
- time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
- return true;
- }
-
- case Ray::POO:
- {
- if ((ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+
+
+ case Ray::PMO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y < box.lo.y)
+ || (ray.jbyi * box.hi.x - box.hi.y + ray.c_xy > 0)
+ || (ray.ibyj * box.lo.y - box.lo.x + ray.c_yx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+ case Ray::PPO:
+ {
+ if((ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x > box.hi.x) || (ray.m_origin.y > box.hi.y)
+ || (ray.jbyi * box.hi.x - box.lo.y + ray.c_xy < 0)
+ || (ray.ibyj * box.hi.y - box.lo.x + ray.c_yx < 0)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ float t1 = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ if (t1 > time) {
+ time = t1;
+ }
+
+ return true;
+ }
+
+
+ case Ray::MOO:
+ {
+ if((ray.m_origin.x < box.lo.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.hi.x - ray.m_origin.x) * ray.m_invDirection.x;
+ return true;
+ }
+
+ case Ray::POO:
+ {
+ if ((ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
+ return true;
+ }
+
+ case Ray::OMO:
+ {
+ if ((ray.m_origin.y < box.lo.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
+ return true;
}
- time = (box.lo.x - ray.m_origin.x) * ray.m_invDirection.x;
- return true;
- }
-
- case Ray::OMO:
- {
- if ((ray.m_origin.y < box.lo.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
- }
-
- time = (box.hi.y - ray.m_origin.y) * ray.m_invDirection.y;
- return true;
- }
-
- case Ray::OPO:
- {
- if ((ray.m_origin.y > box.hi.y)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
- return false;
+ case Ray::OPO:
+ {
+ if ((ray.m_origin.y > box.hi.y)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.z < box.lo.z) || (ray.m_origin.z > box.hi.z)) {
+ return false;
+ }
+
+ time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
+ return true;
}
- time = (box.lo.y - ray.m_origin.y) * ray.m_invDirection.y;
- return true;
- }
+ case Ray::OOM:
+ {
+ if ((ray.m_origin.z < box.lo.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
+ return false;
+ }
- case Ray::OOM:
- {
- if ((ray.m_origin.z < box.lo.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
- return false;
+ time = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
+ return true;
}
- time = (box.hi.z - ray.m_origin.z) * ray.m_invDirection.z;
- return true;
- }
-
- case Ray::OOP:
- {
- if ((ray.m_origin.z > box.hi.z)
- || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
- || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
- return false;
- }
+ case Ray::OOP:
+ {
+ if ((ray.m_origin.z > box.hi.z)
+ || (ray.m_origin.x < box.lo.x) || (ray.m_origin.x > box.hi.x)
+ || (ray.m_origin.y < box.lo.y) || (ray.m_origin.y > box.hi.y)) {
+ return false;
+ }
- time = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
- return true;
- }
- }
+ time = (box.lo.z - ray.m_origin.z) * ray.m_invDirection.z;
+ return true;
+ }
+ }
- return false;
+ return false;
}
#ifdef _MSC_VER
-// Turn off fast floating-point optimizations
+ // Turn off fast floating-point optimizations
#pragma float_control( pop )
#endif
diff --git a/dep/g3dlite/source/Line.cpp b/dep/g3dlite/source/Line.cpp
index 195ae7197f2..2ced4a78bd8 100644
--- a/dep/g3dlite/source/Line.cpp
+++ b/dep/g3dlite/source/Line.cpp
@@ -33,19 +33,19 @@ Vector3 Line::intersection(const Plane& plane) const {
Line::Line(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Line::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- _direction.serialize(b);
+ _point.serialize(b);
+ _direction.serialize(b);
}
void Line::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- _direction.deserialize(b);
+ _point.deserialize(b);
+ _direction.deserialize(b);
}
@@ -80,7 +80,7 @@ Vector3 Line::closestPoint(const Line& B, float& minDist) const {
float t1 = R.dot(U2);
- minDist = abs(P21.dot(M)) / sqrt(m2);
+ minDist = (float)abs(P21.dot(M)) / sqrt(m2);
return P1 + t1 * U1;
}
diff --git a/dep/g3dlite/source/LineSegment.cpp b/dep/g3dlite/source/LineSegment.cpp
index 754600ad554..63a28fce6e6 100644
--- a/dep/g3dlite/source/LineSegment.cpp
+++ b/dep/g3dlite/source/LineSegment.cpp
@@ -80,19 +80,19 @@ bool LineSegment::intersectsSolidSphere(const class Sphere& s) const {
LineSegment::LineSegment(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void LineSegment::serialize(class BinaryOutput& b) const {
- _point.serialize(b);
- direction.serialize(b);
+ _point.serialize(b);
+ direction.serialize(b);
}
void LineSegment::deserialize(class BinaryInput& b) {
- _point.deserialize(b);
- direction.deserialize(b);
+ _point.deserialize(b);
+ direction.deserialize(b);
}
diff --git a/dep/g3dlite/source/Log.cpp b/dep/g3dlite/source/Log.cpp
index f437351cfbd..c113b0b0f79 100644
--- a/dep/g3dlite/source/Log.cpp
+++ b/dep/g3dlite/source/Log.cpp
@@ -14,7 +14,7 @@
#include "G3D/FileSystem.h"
#include <time.h>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <imagehlp.h>
#else
#include <stdarg.h>
@@ -23,16 +23,16 @@
namespace G3D {
void logPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
+ va_list arg_list;
+ va_start(arg_list, fmt);
Log::common()->vprintf(fmt, arg_list);
va_end(arg_list);
}
void logLazyPrintf(const char* fmt, ...) {
- va_list arg_list;
- va_start(arg_list, fmt);
+ va_list arg_list;
+ va_start(arg_list, fmt);
Log::common()->lazyvprintf(fmt, arg_list);
va_end(arg_list);
}
@@ -53,7 +53,7 @@ Log::Log(const std::string& filename, int stripFromStackBottom) :
std::string logName = base + ((ext != "") ? ("." + ext) : "");
// Write time is greater than 1ms. This may be a network drive.... try another file.
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
logName = std::string(std::getenv("TEMP")) + logName;
#else
logName = std::string("/tmp/") + logName;
@@ -86,7 +86,9 @@ Log::~Log() {
Log::commonLog = NULL;
}
- fclose(logFile);
+ if (logFile) {
+ FileSystem::fclose(logFile);
+ }
}
diff --git a/dep/g3dlite/source/Matrix.cpp b/dep/g3dlite/source/Matrix.cpp
index 7a668e59e2c..77188f47e05 100644
--- a/dep/g3dlite/source/Matrix.cpp
+++ b/dep/g3dlite/source/Matrix.cpp
@@ -43,21 +43,21 @@ void Matrix::serialize(TextOutput& t) const {
std::string Matrix::toString(const std::string& name) const {
- std::string s;
+ std::string s;
if (name != "") {
s += format("%s = \n", name.c_str());
}
- s += "[";
+ s += "[";
for (int r = 0; r < rows(); ++r) {
for (int c = 0; c < cols(); ++c) {
double v = impl->get(r, c);
- if (::fabs(v) < 0.00001) {
- // Don't print "negative zero"
+ if (::fabs(v) < 0.00001) {
+ // Don't print "negative zero"
s += format("% 10.04g", 0.0);
- } else if (v == iRound(v)) {
+ } else if (v == iRound(v)) {
// Print integers nicely
s += format("% 10.04g", v);
} else {
@@ -68,20 +68,20 @@ std::string Matrix::toString(const std::string& name) const {
s += ",";
} else if (r < rows() - 1) {
s += ";\n ";
- } else {
- s += "]\n";
- }
+ } else {
+ s += "]\n";
+ }
}
}
- return s;
+ return s;
}
#define INPLACE(OP)\
ImplRef A = impl;\
\
- if (! A.isLastReference()) {\
- impl = new Impl(A->R, A->C);\
+ if (! A.unique()) {\
+ impl.reset(new Impl(A->R, A->C));\
}\
\
A->OP(B, *impl);
@@ -157,9 +157,9 @@ Matrix Matrix::fromDiagonal(const Matrix& d) {
}
void Matrix::set(int r, int c, T v) {
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->set(r, c, v);
}
@@ -174,9 +174,9 @@ void Matrix::setRow(int r, const Matrix& vec) {
debugAssert(r >= 0);
debugAssert(r < rows());
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->setRow(r, vec.impl->data);
}
@@ -192,9 +192,9 @@ void Matrix::setCol(int c, const Matrix& vec) {
debugAssert(c < cols());
- if (! impl.isLastReference()) {
+ if (! impl.unique()) {
// Copy the data before mutating; this object is shared
- impl = new Impl(*impl);
+ impl.reset(new Impl(*impl));
}
impl->setCol(c, vec.impl->data);
}
@@ -272,7 +272,7 @@ Matrix Matrix::identity(int N) {
// Implement an explicit-output unary method by trampolining to the impl
#define TRAMPOLINE_EXPLICIT_1(method)\
void Matrix::method(Matrix& out) const {\
- if ((out.impl == impl) && impl.isLastReference()) {\
+ if ((out.impl == impl) && impl.unique()) {\
impl->method(*out.impl);\
} else {\
out = this->method();\
@@ -289,8 +289,8 @@ TRAMPOLINE_EXPLICIT_1(arraySin)
void Matrix::mulRow(int r, const T& v) {
debugAssert(r >= 0 && r < rows());
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->mulRow(r, v);
@@ -298,7 +298,7 @@ void Matrix::mulRow(int r, const T& v) {
void Matrix::transpose(Matrix& out) const {
- if ((out.impl == impl) && impl.isLastReference() && (impl->R == impl->C)) {
+ if ((out.impl == impl) && impl.unique() && (impl->R == impl->C)) {
// In place
impl->transpose(*out.impl);
} else {
@@ -369,8 +369,8 @@ void Matrix::swapRows(int r0, int r1) {
return;
}
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->swapRows(r0, r1);
@@ -385,8 +385,8 @@ void Matrix::swapAndNegateCols(int c0, int c1) {
return;
}
- if (! impl.isLastReference()) {
- impl = new Impl(*impl);
+ if (! impl.unique()) {
+ impl.reset(new Impl(*impl));
}
impl->swapAndNegateCols(c0, c1);
@@ -432,15 +432,15 @@ void Matrix::svd(Matrix& U, Array<T>& d, Matrix& V, bool sort) const {
int C = cols();
// Make sure we don't overwrite a shared matrix
- if (! V.impl.isLastReference()) {
+ if (! V.impl.unique()) {
V = Matrix::zero(C, C);
} else {
V.impl->setSize(C, C);
}
- if (&U != this || ! impl.isLastReference()) {
+ if (&U != this || ! impl.unique()) {
// Make a copy of this for in-place SVD
- U.impl = new Impl(*impl);
+ U.impl.reset(new Impl(*impl));
}
d.resize(C);
@@ -746,7 +746,7 @@ void Matrix::Impl::inverseViaAdjoint(Impl& out) const {
det += elt[0][r] * out.elt[r][0];
}
- out.div(Matrix::T(det), out);
+ out.div(Matrix::T(det), out);
}
@@ -848,7 +848,7 @@ Matrix::T Matrix::Impl::determinant() const {
float cofactor10 = elt[1][2] * elt[2][0] - elt[1][0] * elt[2][2];
float cofactor20 = elt[1][0] * elt[2][1] - elt[1][1] * elt[2][0];
- return Matrix::T(
+ return Matrix::T(
elt[0][0] * cofactor00 +
elt[0][1] * cofactor10 +
elt[0][2] * cofactor20);
@@ -896,10 +896,11 @@ Matrix Matrix::pseudoInverse(float tolerance) const {
Public function for testing purposes only. Use pseudoInverse(), as it contains optimizations for
nonsingular matrices with at least one small (<5) dimension.
*/
+// See http://en.wikipedia.org/wiki/Moore%E2%80%93Penrose_pseudoinverse
Matrix Matrix::svdPseudoInverse(float tolerance) const {
- if (cols() > rows()) {
- return transpose().svdPseudoInverse(tolerance).transpose();
- }
+ if (cols() > rows()) {
+ return transpose().svdPseudoInverse(tolerance).transpose();
+ }
// Matrices from SVD
Matrix U, V;
@@ -907,32 +908,32 @@ Matrix Matrix::svdPseudoInverse(float tolerance) const {
// Diagonal elements
Array<T> d;
- svd(U, d, V);
+ svd(U, d, V);
if (rows() == 1) {
d.resize(1, false);
}
- if (tolerance < 0) {
- // TODO: Should be eps(d[0]), which is the largest diagonal
- tolerance = G3D::max(rows(), cols()) * 0.0001f;
- }
-
- Matrix X;
-
- int r = 0;
- for (int i = 0; i < d.size(); ++i) {
- if (d[i] > tolerance) {
- d[i] = Matrix::T(1) / d[i];
- ++r;
- }
- }
+ if (tolerance < 0) {
+ // TODO: Should be eps(d[0]), which is the largest diagonal
+ tolerance = G3D::max(rows(), cols()) * 0.0001f;
+ }
- if (r == 0) {
- // There were no non-zero elements
- X = zero(cols(), rows());
- } else {
- // Use the first r columns
+ Matrix X;
+
+ int r = 0;
+ for (int i = 0; i < d.size(); ++i) {
+ if (d[i] > tolerance) {
+ d[i] = Matrix::T(1) / d[i];
+ ++r;
+ }
+ }
+
+ if (r == 0) {
+ // There were no non-zero elements
+ X = zero(cols(), rows());
+ } else {
+ // Use the first r columns
// Test code (the rest is below)
/*
@@ -1003,7 +1004,8 @@ Matrix Matrix::svdPseudoInverse(float tolerance) const {
debugAssert(n < 0.0001);
*/
}
- return X;
+
+ return X;
}
// Computes pseudoinverse for a vector
@@ -1426,7 +1428,7 @@ void Matrix::Impl::inverseInPlaceGaussJordan() {
elt[col][col] = 1.0;
for (int k = 0; k < R; ++k) {
- elt[col][k] *= Matrix::T(pivotInverse);
+ elt[col][k] *= Matrix::T(pivotInverse);
}
// Reduce all rows
@@ -1438,7 +1440,7 @@ void Matrix::Impl::inverseInPlaceGaussJordan() {
elt[r][col] = 0.0;
for (int k = 0; k < R; ++k) {
- elt[r][k] -= Matrix::T(elt[col][k] * oldValue);
+ elt[r][k] -= Matrix::T(elt[col][k] * oldValue);
}
}
}
@@ -1537,13 +1539,12 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
f = (double)U[i][i];
- // TODO: what is this 2-arg sign function?
- g = -SIGN(sqrt(s), f);
+ g = -sign(f)*(sqrt(s));
h = f * g - s;
U[i][i] = (float)(f - g);
if (i != cols - 1) {
- for (j = l; j < cols; j++) {
+ for (j = l; j < cols; ++j) {
for (s = 0.0, k = i; k < rows; ++k) {
s += ((double)U[k][i] * (double)U[k][j]);
@@ -1610,13 +1611,13 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
for (i = cols - 1; i >= 0; --i) {
if (i < cols - 1) {
if (g) {
- for (j = l; j < cols; j++) {
+ for (j = l; j < cols; ++j) {
V[j][i] = (float)(((double)U[i][j] / (double)U[i][l]) / g);
}
// double division to avoid underflow
for (j = l; j < cols; ++j) {
- for (s = 0.0, k = l; k < cols; k++) {
+ for (s = 0.0, k = l; k < cols; ++k) {
s += ((double)U[i][k] * (double)V[k][j]);
}
@@ -1778,7 +1779,7 @@ const char* Matrix::svdCore(float** U, int rows, int cols, float* D, float** V)
}
f = (c * g) + (s * y);
x = (c * y) - (s * g);
- for (jj = 0; jj < rows; jj++) {
+ for (jj = 0; jj < rows; ++jj) {
y = (double)U[jj][j];
z = (double)U[jj][i];
U[jj][j] = (float)(y * c + z * s);
diff --git a/dep/g3dlite/source/Matrix3.cpp b/dep/g3dlite/source/Matrix3.cpp
index 7e4de99621a..2f704c8f87b 100644
--- a/dep/g3dlite/source/Matrix3.cpp
+++ b/dep/g3dlite/source/Matrix3.cpp
@@ -6,9 +6,9 @@
@author Morgan McGuire, graphics3d.com
@created 2001-06-02
- @edited 2009-11-15
+ @edited 2010-08-15
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -32,7 +32,12 @@ Matrix3::Matrix3(const Any& any) {
if (any.nameEquals("Matrix3::fromAxisAngle")) {
any.verifySize(2);
- *this = Matrix3::fromAxisAngle(any[0], any[1].number());
+ *this = fromAxisAngle(Vector3(any[0]), any[1].floatValue());
+ } else if (any.nameEquals("Matrix3::diagonal")) {
+ any.verifySize(3);
+ *this = diagonal(any[0], any[1], any[2]);
+ } else if (any.nameEquals("Matrix3::identity")) {
+ *this = identity();
} else {
any.verifySize(9);
@@ -45,7 +50,7 @@ Matrix3::Matrix3(const Any& any) {
}
-Matrix3::operator Any() const {
+Any Matrix3::toAny() const {
Any any(Any::ARRAY, "Matrix3");
any.resize(9);
for (int r = 0; r < 3; ++r) {
@@ -116,7 +121,7 @@ bool Matrix3::isOrthonormal() const {
//----------------------------------------------------------------------------
Matrix3::Matrix3(const Quat& _q) {
// Implementation from Watt and Watt, pg 362
- // See also http://www.flipcode.com/documents/matrfaq.html#Q54
+ // See also http://www.flipcode.com/documents/matrfaq.html#Q54
Quat q = _q;
q.unitize();
float xx = 2.0f * q.x * q.x;
@@ -226,8 +231,8 @@ void Matrix3::setRow(int iRow, const Vector3 &vector) {
//----------------------------------------------------------------------------
bool Matrix3::operator== (const Matrix3& rkMatrix) const {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
if ( elt[iRow][iCol] != rkMatrix.elt[iRow][iCol] )
return false;
}
@@ -245,8 +250,8 @@ bool Matrix3::operator!= (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const {
Matrix3 kSum;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kSum.elt[iRow][iCol] = elt[iRow][iCol] +
rkMatrix.elt[iRow][iCol];
}
@@ -259,8 +264,8 @@ Matrix3 Matrix3::operator+ (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const {
Matrix3 kDiff;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kDiff.elt[iRow][iCol] = elt[iRow][iCol] -
rkMatrix.elt[iRow][iCol];
}
@@ -273,8 +278,8 @@ Matrix3 Matrix3::operator- (const Matrix3& rkMatrix) const {
Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kProd.elt[iRow][iCol] =
elt[iRow][0] * rkMatrix.elt[0][iCol] +
elt[iRow][1] * rkMatrix.elt[1][iCol] +
@@ -286,8 +291,8 @@ Matrix3 Matrix3::operator* (const Matrix3& rkMatrix) const {
}
Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = elt[iRow][iCol] + rkMatrix.elt[iRow][iCol];
}
}
@@ -296,8 +301,8 @@ Matrix3& Matrix3::operator+= (const Matrix3& rkMatrix) {
}
Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = elt[iRow][iCol] - rkMatrix.elt[iRow][iCol];
}
}
@@ -307,8 +312,8 @@ Matrix3& Matrix3::operator-= (const Matrix3& rkMatrix) {
Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) {
Matrix3 mulMat;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
mulMat.elt[iRow][iCol] =
elt[iRow][0] * rkMatrix.elt[0][iCol] +
elt[iRow][1] * rkMatrix.elt[1][iCol] +
@@ -324,8 +329,8 @@ Matrix3& Matrix3::operator*= (const Matrix3& rkMatrix) {
Matrix3 Matrix3::operator- () const {
Matrix3 kNeg;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kNeg[iRow][iCol] = -elt[iRow][iCol];
}
}
@@ -337,8 +342,8 @@ Matrix3 Matrix3::operator- () const {
Matrix3 Matrix3::operator* (float fScalar) const {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kProd[iRow][iCol] = fScalar * elt[iRow][iCol];
}
}
@@ -352,8 +357,8 @@ Matrix3& Matrix3::operator/= (float fScalar) {
Matrix3& Matrix3::operator*= (float fScalar) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] *= fScalar;
}
}
@@ -365,9 +370,9 @@ Matrix3& Matrix3::operator*= (float fScalar) {
Matrix3 operator* (double fScalar, const Matrix3& rkMatrix) {
Matrix3 kProd;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
- kProd[iRow][iCol] = fScalar * rkMatrix.elt[iRow][iCol];
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
+ kProd[iRow][iCol] = (float)fScalar * rkMatrix.elt[iRow][iCol];
}
}
@@ -386,8 +391,8 @@ Matrix3 operator* (int fScalar, const Matrix3& rkMatrix) {
Matrix3 Matrix3::transpose () const {
Matrix3 kTranspose;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
kTranspose[iRow][iCol] = elt[iCol][iRow];
}
}
@@ -427,10 +432,10 @@ bool Matrix3::inverse (Matrix3& rkInverse, float fTolerance) const {
if ( G3D::abs(fDet) <= fTolerance )
return false;
- float fInvDet = 1.0 / fDet;
+ float fInvDet = 1.0f / fDet;
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++)
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol)
rkInverse[iRow][iCol] *= fInvDet;
}
@@ -473,13 +478,13 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][0] * kA[2][0]);
if ( fLength > 0.0 ) {
- fSign = (kA[0][0] > 0.0 ? 1.0 : -1.0);
- fT1 = kA[0][0] + fSign * fLength;
- fInvT1 = 1.0 / fT1;
+ fSign = (kA[0][0] > 0.0 ? 1.0f : -1.0f);
+ fT1 = (float)kA[0][0] + fSign * fLength;
+ fInvT1 = 1.0f / fT1;
afV[1] = kA[1][0] * fInvT1;
afV[2] = kA[2][0] * fInvT1;
- fT2 = -2.0 / (1.0 + afV[1] * afV[1] + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[1] * afV[1] + afV[2] * afV[2]);
afW[0] = fT2 * (kA[0][0] + kA[1][0] * afV[1] + kA[2][0] * afV[2]);
afW[1] = fT2 * (kA[0][1] + kA[1][1] * afV[1] + kA[2][1] * afV[2]);
afW[2] = fT2 * (kA[0][2] + kA[1][2] * afV[1] + kA[2][2] * afV[2]);
@@ -491,12 +496,12 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][1] += afV[2] * afW[1];
kA[2][2] += afV[2] * afW[2];
- kL[0][0] = 1.0 + fT2;
+ kL[0][0] = 1.0f + fT2;
kL[0][1] = kL[1][0] = fT2 * afV[1];
kL[0][2] = kL[2][0] = fT2 * afV[2];
- kL[1][1] = 1.0 + fT2 * afV[1] * afV[1];
+ kL[1][1] = 1.0f + fT2 * afV[1] * afV[1];
kL[1][2] = kL[2][1] = fT2 * afV[1] * afV[2];
- kL[2][2] = 1.0 + fT2 * afV[2] * afV[2];
+ kL[2][2] = 1.0f + fT2 * afV[2] * afV[2];
bIdentity = false;
} else {
kL = Matrix3::identity();
@@ -507,11 +512,11 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
fLength = sqrt(kA[0][1] * kA[0][1] + kA[0][2] * kA[0][2]);
if ( fLength > 0.0 ) {
- fSign = (kA[0][1] > 0.0 ? 1.0 : -1.0);
+ fSign = (kA[0][1] > 0.0 ? 1.0f : -1.0f);
fT1 = kA[0][1] + fSign * fLength;
afV[2] = kA[0][2] / fT1;
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
afW[0] = fT2 * (kA[0][1] + kA[0][2] * afV[2]);
afW[1] = fT2 * (kA[1][1] + kA[1][2] * afV[2]);
afW[2] = fT2 * (kA[2][1] + kA[2][2] * afV[2]);
@@ -521,12 +526,12 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kA[2][1] += afW[2];
kA[2][2] += afW[2] * afV[2];
- kR[0][0] = 1.0;
- kR[0][1] = kR[1][0] = 0.0;
- kR[0][2] = kR[2][0] = 0.0;
- kR[1][1] = 1.0 + fT2;
+ kR[0][0] = 1.0f;
+ kR[0][1] = kR[1][0] = 0.0f;
+ kR[0][2] = kR[2][0] = 0.0f;
+ kR[1][1] = 1.0f + fT2;
kR[1][2] = kR[2][1] = fT2 * afV[2];
- kR[2][2] = 1.0 + fT2 * afV[2] * afV[2];
+ kR[2][2] = 1.0f + fT2 * afV[2] * afV[2];
} else {
kR = Matrix3::identity();
}
@@ -535,20 +540,20 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
fLength = sqrt(kA[1][1] * kA[1][1] + kA[2][1] * kA[2][1]);
if ( fLength > 0.0 ) {
- fSign = (kA[1][1] > 0.0 ? 1.0 : -1.0);
+ fSign = (kA[1][1] > 0.0 ? 1.0f : -1.0f);
fT1 = kA[1][1] + fSign * fLength;
afV[2] = kA[2][1] / fT1;
- fT2 = -2.0 / (1.0 + afV[2] * afV[2]);
+ fT2 = -2.0f / (1.0f + afV[2] * afV[2]);
afW[1] = fT2 * (kA[1][1] + kA[2][1] * afV[2]);
afW[2] = fT2 * (kA[1][2] + kA[2][2] * afV[2]);
kA[1][1] += afW[1];
kA[1][2] += afW[2];
kA[2][2] += afV[2] * afW[2];
- float fA = 1.0 + fT2;
+ float fA = 1.0f + fT2;
float fB = fT2 * afV[2];
- float fC = 1.0 + fB * afV[2];
+ float fC = 1.0f + fB * afV[2];
if ( bIdentity ) {
kL[0][0] = 1.0;
@@ -558,7 +563,7 @@ void Matrix3::bidiagonalize (Matrix3& kA, Matrix3& kL,
kL[1][2] = kL[2][1] = fB;
kL[2][2] = fC;
} else {
- for (int iRow = 0; iRow < 3; iRow++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
float fTmp0 = kL[iRow][1];
float fTmp1 = kL[iRow][2];
kL[iRow][1] = fA * fTmp0 + fB * fTmp1;
@@ -576,15 +581,15 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
float fT12 = kA[1][1] * kA[1][2];
float fTrace = fT11 + fT22;
float fDiff = fT11 - fT22;
- float fDiscr = sqrt(fDiff * fDiff + 4.0 * fT12 * fT12);
- float fRoot1 = 0.5 * (fTrace + fDiscr);
- float fRoot2 = 0.5 * (fTrace - fDiscr);
+ float fDiscr = sqrt(fDiff * fDiff + 4.0f * fT12 * fT12);
+ float fRoot1 = 0.5f * (fTrace + fDiscr);
+ float fRoot2 = 0.5f * (fTrace - fDiscr);
// adjust right
float fY = kA[0][0] - (G3D::abs(fRoot1 - fT22) <=
G3D::abs(fRoot2 - fT22) ? fRoot1 : fRoot2);
float fZ = kA[0][1];
- float fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ float fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
float fSin = fZ * fInvLength;
float fCos = -fY * fInvLength;
@@ -597,7 +602,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
int iRow;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[0][iRow];
fTmp1 = kR[1][iRow];
kR[0][iRow] = fCos * fTmp0 - fSin * fTmp1;
@@ -609,7 +614,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[1][0];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -631,7 +636,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
int iCol;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][0];
fTmp1 = kL[iCol][1];
kL[iCol][0] = fCos * fTmp0 - fSin * fTmp1;
@@ -643,7 +648,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[0][2];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -663,7 +668,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
kA[2][2] *= fCos;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[1][iRow];
fTmp1 = kR[2][iRow];
kR[1][iRow] = fCos * fTmp0 - fSin * fTmp1;
@@ -675,7 +680,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
fZ = kA[2][1];
- fInvLength = 1.0 / sqrt(fY * fY + fZ * fZ);
+ fInvLength = 1.0f / sqrt(fY * fY + fZ * fZ);
fSin = fZ * fInvLength;
@@ -691,7 +696,7 @@ void Matrix3::golubKahanStep (Matrix3& kA, Matrix3& kL,
kA[2][2] = fSin * fTmp0 + fCos * fTmp1;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][1];
fTmp1 = kL[iCol][2];
kL[iCol][1] = fCos * fTmp0 - fSin * fTmp1;
@@ -707,7 +712,7 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
Matrix3 kA = *this;
bidiagonalize(kA, kL, kR);
- for (int i = 0; i < ms_iSvdMaxIterations; i++) {
+ for (int i = 0; i < ms_iSvdMaxIterations; ++i) {
float fTmp, fTmp0, fTmp1;
float fSin0, fCos0, fTan0;
float fSin1, fCos1, fTan1;
@@ -727,11 +732,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
// 2x2 closed form factorization
fTmp = (kA[1][1] * kA[1][1] - kA[2][2] * kA[2][2] +
kA[1][2] * kA[1][2]) / (kA[1][2] * kA[2][2]);
- fTan0 = 0.5 * (fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
+ fTan0 = 0.5f * (fTmp + sqrt(fTmp * fTmp + 4.0f));
+ fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
fSin0 = fTan0 * fCos0;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][1];
fTmp1 = kL[iCol][2];
kL[iCol][1] = fCos0 * fTmp0 - fSin0 * fTmp1;
@@ -739,10 +744,10 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
fTan1 = (kA[1][2] - kA[2][2] * fTan0) / kA[1][1];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
+ fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
fSin1 = -fTan1 * fCos1;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[1][iRow];
fTmp1 = kR[2][iRow];
kR[1][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
@@ -761,11 +766,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
// 2x2 closed form factorization
fTmp = (kA[0][0] * kA[0][0] + kA[1][1] * kA[1][1] -
kA[0][1] * kA[0][1]) / (kA[0][1] * kA[1][1]);
- fTan0 = 0.5 * ( -fTmp + sqrt(fTmp * fTmp + 4.0));
- fCos0 = 1.0 / sqrt(1.0 + fTan0 * fTan0);
+ fTan0 = 0.5f * ( -fTmp + sqrt(fTmp * fTmp + 4.0f));
+ fCos0 = 1.0f / sqrt(1.0f + fTan0 * fTan0);
fSin0 = fTan0 * fCos0;
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iCol = 0; iCol < 3; ++iCol) {
fTmp0 = kL[iCol][0];
fTmp1 = kL[iCol][1];
kL[iCol][0] = fCos0 * fTmp0 - fSin0 * fTmp1;
@@ -773,10 +778,10 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
fTan1 = (kA[0][1] - kA[1][1] * fTan0) / kA[0][0];
- fCos1 = 1.0 / sqrt(1.0 + fTan1 * fTan1);
+ fCos1 = 1.0f / sqrt(1.0f + fTan1 * fTan1);
fSin1 = -fTan1 * fCos1;
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
fTmp0 = kR[0][iRow];
fTmp1 = kR[1][iRow];
kR[0][iRow] = fCos1 * fTmp0 - fSin1 * fTmp1;
@@ -796,11 +801,11 @@ void Matrix3::singularValueDecomposition (Matrix3& kL, Vector3& kS,
}
// positize diagonal
- for (iRow = 0; iRow < 3; iRow++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
if ( kS[iRow] < 0.0 ) {
kS[iRow] = -kS[iRow];
- for (iCol = 0; iCol < 3; iCol++)
+ for (iCol = 0; iCol < 3; ++iCol)
kR[iRow][iCol] = -kR[iRow][iCol];
}
}
@@ -813,17 +818,17 @@ void Matrix3::singularValueComposition (const Matrix3& kL,
Matrix3 kTmp;
// product S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol)
kTmp[iRow][iCol] = kS[iRow] * kR[iRow][iCol];
}
// product L*S*R
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol) {
elt[iRow][iCol] = 0.0;
- for (int iMid = 0; iMid < 3; iMid++)
+ for (int iMid = 0; iMid < 3; ++iMid)
elt[iRow][iCol] += kL[iRow][iMid] * kTmp[iMid][iCol];
}
}
@@ -842,7 +847,7 @@ void Matrix3::orthonormalize () {
// product of vectors A and B.
// compute q0
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
+ float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
+ elt[1][0] * elt[1][0] +
elt[2][0] * elt[2][0]);
@@ -860,7 +865,7 @@ void Matrix3::orthonormalize () {
elt[1][1] -= fDot0 * elt[1][0];
elt[2][1] -= fDot0 * elt[2][0];
- fInvLength = 1.0 / sqrt(elt[0][1] * elt[0][1] +
+ fInvLength = 1.0f / sqrt(elt[0][1] * elt[0][1] +
elt[1][1] * elt[1][1] +
elt[2][1] * elt[2][1]);
@@ -883,7 +888,7 @@ void Matrix3::orthonormalize () {
elt[1][2] -= fDot0 * elt[1][0] + fDot1 * elt[1][1];
elt[2][2] -= fDot0 * elt[2][0] + fDot1 * elt[2][1];
- fInvLength = 1.0 / sqrt(elt[0][2] * elt[0][2] +
+ fInvLength = 1.0f / sqrt(elt[0][2] * elt[0][2] +
elt[1][2] * elt[1][2] +
elt[2][2] * elt[2][2]);
@@ -923,7 +928,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
// U stores the entries U[0] = u01, U[1] = u02, U[2] = u12
// build orthogonal matrix Q
- float fInvLength = 1.0 / sqrt(elt[0][0] * elt[0][0]
+ float fInvLength = 1.0f / sqrt(elt[0][0] * elt[0][0]
+ elt[1][0] * elt[1][0] +
elt[2][0] * elt[2][0]);
kQ[0][0] = elt[0][0] * fInvLength;
@@ -935,7 +940,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][1] = elt[0][1] - fDot * kQ[0][0];
kQ[1][1] = elt[1][1] - fDot * kQ[1][0];
kQ[2][1] = elt[2][1] - fDot * kQ[2][0];
- fInvLength = 1.0 / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
+ fInvLength = 1.0f / sqrt(kQ[0][1] * kQ[0][1] + kQ[1][1] * kQ[1][1] +
kQ[2][1] * kQ[2][1]);
kQ[0][1] *= fInvLength;
kQ[1][1] *= fInvLength;
@@ -951,7 +956,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][2] -= fDot * kQ[0][1];
kQ[1][2] -= fDot * kQ[1][1];
kQ[2][2] -= fDot * kQ[2][1];
- fInvLength = 1.0 / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
+ fInvLength = 1.0f / sqrt(kQ[0][2] * kQ[0][2] + kQ[1][2] * kQ[1][2] +
kQ[2][2] * kQ[2][2]);
kQ[0][2] *= fInvLength;
kQ[1][2] *= fInvLength;
@@ -963,8 +968,8 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kQ[0][1] * kQ[1][0] * kQ[2][2] - kQ[0][0] * kQ[1][2] * kQ[2][1];
if ( fDet < 0.0 ) {
- for (int iRow = 0; iRow < 3; iRow++)
- for (int iCol = 0; iCol < 3; iCol++)
+ for (int iRow = 0; iRow < 3; ++iRow)
+ for (int iCol = 0; iCol < 3; ++iCol)
kQ[iRow][iCol] = -kQ[iRow][iCol];
}
@@ -997,7 +1002,7 @@ void Matrix3::qDUDecomposition (Matrix3& kQ,
kD[2] = kR[2][2];
// the shear component
- float fInvD0 = 1.0 / kD[0];
+ float fInvD0 = 1.0f / kD[0];
kU[0] = kR[0][1] * fInvD0;
@@ -1031,7 +1036,7 @@ void Matrix3::polarDecomposition(Matrix3 &R, Matrix3 &S) const{
const int MAX_ITERS = 100;
const double eps = 50 * std::numeric_limits<float>::epsilon();
- const float BigEps = 50 * eps;
+ const float BigEps = 50.0f * (float)eps;
/* Higham suggests using OneNorm(Xit-X) < eps * OneNorm(X)
* as the convergence criterion, but OneNorm(X) should quickly
@@ -1046,23 +1051,23 @@ void Matrix3::polarDecomposition(Matrix3 &R, Matrix3 &S) const{
Xit = tmp.transpose();
if (resid < BigEps) {
- // close enough use simple iteration
- X += Xit;
- X *= 0.5f;
+ // close enough use simple iteration
+ X += Xit;
+ X *= 0.5f;
}
else {
- // not close to convergence, compute acceleration factor
+ // not close to convergence, compute acceleration factor
float gamma = sqrt( sqrt(
(Xit.l1Norm()* Xit.lInfNorm())/(X.l1Norm()*X.lInfNorm()) ) );
- X *= 0.5f * gamma;
- tmp = Xit;
- tmp *= 0.5f / gamma;
- X += tmp;
+ X *= 0.5f * gamma;
+ tmp = Xit;
+ tmp *= 0.5f / gamma;
+ X += tmp;
}
resid = X.diffOneNorm(Xit);
- iter++;
+ ++iter;
}
R = X;
@@ -1119,13 +1124,13 @@ float Matrix3::maxCubicRoot (float afCoeff[3]) {
if ( fPoly < 0.0f ) {
// uses a matrix norm to find an upper bound on maximum root
- fX = G3D::abs(afCoeff[0]);
- float fTmp = 1.0 + G3D::abs(afCoeff[1]);
+ fX = (float)G3D::abs(afCoeff[0]);
+ float fTmp = 1.0f + (float)G3D::abs(afCoeff[1]);
if ( fTmp > fX )
fX = fTmp;
- fTmp = 1.0 + G3D::abs(afCoeff[2]);
+ fTmp = 1.0f + (float)G3D::abs(afCoeff[2]);
if ( fTmp > fX )
fX = fTmp;
@@ -1134,7 +1139,7 @@ float Matrix3::maxCubicRoot (float afCoeff[3]) {
// Newton's method to find root
float fTwoC2 = 2.0f * afCoeff[2];
- for (int i = 0; i < 16; i++) {
+ for (int i = 0; i < 16; ++i) {
fPoly = afCoeff[0] + fX * (afCoeff[1] + fX * (afCoeff[2] + fX));
if ( G3D::abs(fPoly) <= fEpsilon )
@@ -1154,11 +1159,11 @@ float Matrix3::spectralNorm () const {
int iRow, iCol;
float fPmax = 0.0;
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++) {
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol) {
kP[iRow][iCol] = 0.0;
- for (int iMid = 0; iMid < 3; iMid++) {
+ for (int iMid = 0; iMid < 3; ++iMid) {
kP[iRow][iCol] +=
elt[iMid][iRow] * elt[iMid][iCol];
}
@@ -1168,10 +1173,10 @@ float Matrix3::spectralNorm () const {
}
}
- float fInvPmax = 1.0 / fPmax;
+ float fInvPmax = 1.0f / fPmax;
- for (iRow = 0; iRow < 3; iRow++) {
- for (iCol = 0; iCol < 3; iCol++)
+ for (iRow = 0; iRow < 3; ++iRow) {
+ for (iCol = 0; iCol < 3; ++iCol)
kP[iRow][iCol] *= fInvPmax;
}
@@ -1215,7 +1220,7 @@ float Matrix3::l1Norm() const {
float f = fabs(elt[0][c])+ fabs(elt[1][c]) + fabs(elt[2][c]);
if (f > oneNorm) {
- oneNorm = f;
+ oneNorm = f;
}
}
return oneNorm;
@@ -1231,7 +1236,7 @@ float Matrix3::lInfNorm() const {
float f = fabs(elt[r][0]) + fabs(elt[r][1])+ fabs(elt[r][2]);
if (f > infNorm) {
- infNorm = f;
+ infNorm = f;
}
}
return infNorm;
@@ -1244,10 +1249,10 @@ float Matrix3::diffOneNorm(const Matrix3 &y) const{
for (int c = 0; c < 3; ++c){
float f = fabs(elt[0][c] - y[0][c]) + fabs(elt[1][c] - y[1][c])
- + fabs(elt[2][c] - y[2][c]);
+ + fabs(elt[2][c] - y[2][c]);
if (f > oneNorm) {
- oneNorm = f;
+ oneNorm = f;
}
}
return oneNorm;
@@ -1280,14 +1285,14 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
float fTrace = elt[0][0] + elt[1][1] + elt[2][2];
float fCos = 0.5f * (fTrace - 1.0f);
- rfRadians = G3D::aCos(fCos); // in [0,PI]
+ rfRadians = (float)G3D::aCos(fCos); // in [0,PI]
if ( rfRadians > 0.0 ) {
if ( rfRadians < pi() ) {
rkAxis.x = elt[2][1] - elt[1][2];
rkAxis.y = elt[0][2] - elt[2][0];
rkAxis.z = elt[1][0] - elt[0][1];
- rkAxis.unitize();
+ rkAxis = rkAxis.direction();
} else {
// angle is PI
float fHalfInverse;
@@ -1296,16 +1301,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
// r00 >= r11
if ( elt[0][0] >= elt[2][2] ) {
// r00 is maximum diagonal term
- rkAxis.x = 0.5 * sqrt(elt[0][0] -
- elt[1][1] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.x;
+ rkAxis.x = 0.5f * sqrt(elt[0][0] -
+ elt[1][1] - elt[2][2] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.x;
rkAxis.y = fHalfInverse * elt[0][1];
rkAxis.z = fHalfInverse * elt[0][2];
} else {
// r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
+ rkAxis.z = 0.5f * sqrt(elt[2][2] -
+ elt[0][0] - elt[1][1] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.z;
rkAxis.x = fHalfInverse * elt[0][2];
rkAxis.y = fHalfInverse * elt[1][2];
}
@@ -1313,16 +1318,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
// r11 > r00
if ( elt[1][1] >= elt[2][2] ) {
// r11 is maximum diagonal term
- rkAxis.y = 0.5 * sqrt(elt[1][1] -
- elt[0][0] - elt[2][2] + 1.0);
- fHalfInverse = 0.5 / rkAxis.y;
+ rkAxis.y = 0.5f * sqrt(elt[1][1] -
+ elt[0][0] - elt[2][2] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.y;
rkAxis.x = fHalfInverse * elt[0][1];
rkAxis.z = fHalfInverse * elt[1][2];
} else {
// r22 is maximum diagonal term
- rkAxis.z = 0.5 * sqrt(elt[2][2] -
- elt[0][0] - elt[1][1] + 1.0);
- fHalfInverse = 0.5 / rkAxis.z;
+ rkAxis.z = 0.5f * sqrt(elt[2][2] -
+ elt[0][0] - elt[1][1] + 1.0f);
+ fHalfInverse = 0.5f / rkAxis.z;
rkAxis.x = fHalfInverse * elt[0][2];
rkAxis.y = fHalfInverse * elt[1][2];
}
@@ -1339,12 +1344,16 @@ void Matrix3::toAxisAngle (Vector3& rkAxis, float& rfRadians) const {
//----------------------------------------------------------------------------
Matrix3 Matrix3::fromAxisAngle (const Vector3& _axis, float fRadians) {
- Vector3 axis = _axis.direction();
+ return fromUnitAxisAngle(_axis.direction(), fRadians);
+}
+
+Matrix3 Matrix3::fromUnitAxisAngle (const Vector3& axis, float fRadians) {
+ debugAssertM(axis.isUnit(), "Matrix3::fromUnitAxisAngle requires ||axis|| = 1");
Matrix3 m;
float fCos = cos(fRadians);
float fSin = sin(fRadians);
- float fOneMinusCos = 1.0 - fCos;
+ float fOneMinusCos = 1.0f - fCos;
float fX2 = square(axis.x);
float fY2 = square(axis.y);
float fZ2 = square(axis.z);
@@ -1379,20 +1388,20 @@ bool Matrix3::toEulerAnglesXYZ (float& rfXAngle, float& rfYAngle,
if ( elt[0][2] < 1.0f ) {
if ( elt[0][2] > -1.0f ) {
- rfXAngle = G3D::aTan2( -elt[1][2], elt[2][2]);
+ rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[2][2]);
rfYAngle = (float) G3D::aSin(elt[0][2]);
- rfZAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
+ rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[0][0]);
return true;
} else {
// WARNING. Not unique. XA - ZA = -atan2(r10,r11)
- rfXAngle = -G3D::aTan2(elt[1][0], elt[1][1]);
+ rfXAngle = -(float)G3D::aTan2(elt[1][0], elt[1][1]);
rfYAngle = -(float)halfPi();
rfZAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. XAngle + ZAngle = atan2(r10,r11)
- rfXAngle = G3D::aTan2(elt[1][0], elt[1][1]);
+ rfXAngle = (float)G3D::aTan2(elt[1][0], elt[1][1]);
rfYAngle = (float)halfPi();
rfZAngle = 0.0f;
return false;
@@ -1408,20 +1417,20 @@ bool Matrix3::toEulerAnglesXZY (float& rfXAngle, float& rfZAngle,
if ( elt[0][1] < 1.0f ) {
if ( elt[0][1] > -1.0f ) {
- rfXAngle = G3D::aTan2(elt[2][1], elt[1][1]);
+ rfXAngle = (float) G3D::aTan2(elt[2][1], elt[1][1]);
rfZAngle = (float) asin( -elt[0][1]);
- rfYAngle = G3D::aTan2(elt[0][2], elt[0][0]);
+ rfYAngle = (float) G3D::aTan2(elt[0][2], elt[0][0]);
return true;
} else {
// WARNING. Not unique. XA - YA = atan2(r20,r22)
- rfXAngle = G3D::aTan2(elt[2][0], elt[2][2]);
+ rfXAngle = (float)G3D::aTan2(elt[2][0], elt[2][2]);
rfZAngle = (float)halfPi();
- rfYAngle = 0.0;
+ rfYAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. XA + YA = atan2(-r20,r22)
- rfXAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
+ rfXAngle = (float)G3D::aTan2( -elt[2][0], elt[2][2]);
rfZAngle = -(float)halfPi();
rfYAngle = 0.0f;
return false;
@@ -1437,20 +1446,20 @@ bool Matrix3::toEulerAnglesYXZ (float& rfYAngle, float& rfXAngle,
if ( elt[1][2] < 1.0 ) {
if ( elt[1][2] > -1.0 ) {
- rfYAngle = G3D::aTan2(elt[0][2], elt[2][2]);
+ rfYAngle = (float) G3D::aTan2(elt[0][2], elt[2][2]);
rfXAngle = (float) asin( -elt[1][2]);
- rfZAngle = G3D::aTan2(elt[1][0], elt[1][1]);
+ rfZAngle = (float) G3D::aTan2(elt[1][0], elt[1][1]);
return true;
} else {
// WARNING. Not unique. YA - ZA = atan2(r01,r00)
- rfYAngle = G3D::aTan2(elt[0][1], elt[0][0]);
+ rfYAngle = (float)G3D::aTan2(elt[0][1], elt[0][0]);
rfXAngle = (float)halfPi();
- rfZAngle = 0.0;
+ rfZAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. YA + ZA = atan2(-r01,r00)
- rfYAngle = G3D::aTan2( -elt[0][1], elt[0][0]);
+ rfYAngle = (float)G3D::aTan2( -elt[0][1], elt[0][0]);
rfXAngle = -(float)halfPi();
rfZAngle = 0.0f;
return false;
@@ -1466,20 +1475,20 @@ bool Matrix3::toEulerAnglesYZX (float& rfYAngle, float& rfZAngle,
if ( elt[1][0] < 1.0 ) {
if ( elt[1][0] > -1.0 ) {
- rfYAngle = G3D::aTan2( -elt[2][0], elt[0][0]);
+ rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[0][0]);
rfZAngle = (float) asin(elt[1][0]);
- rfXAngle = G3D::aTan2( -elt[1][2], elt[1][1]);
+ rfXAngle = (float) G3D::aTan2( -elt[1][2], elt[1][1]);
return true;
} else {
// WARNING. Not unique. YA - XA = -atan2(r21,r22);
- rfYAngle = -G3D::aTan2(elt[2][1], elt[2][2]);
+ rfYAngle = -(float)G3D::aTan2(elt[2][1], elt[2][2]);
rfZAngle = -(float)halfPi();
- rfXAngle = 0.0;
+ rfXAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. YA + XA = atan2(r21,r22)
- rfYAngle = G3D::aTan2(elt[2][1], elt[2][2]);
+ rfYAngle = (float)G3D::aTan2(elt[2][1], elt[2][2]);
rfZAngle = (float)halfPi();
rfXAngle = 0.0f;
return false;
@@ -1495,20 +1504,20 @@ bool Matrix3::toEulerAnglesZXY (float& rfZAngle, float& rfXAngle,
if ( elt[2][1] < 1.0 ) {
if ( elt[2][1] > -1.0 ) {
- rfZAngle = G3D::aTan2( -elt[0][1], elt[1][1]);
+ rfZAngle = (float) G3D::aTan2( -elt[0][1], elt[1][1]);
rfXAngle = (float) asin(elt[2][1]);
- rfYAngle = G3D::aTan2( -elt[2][0], elt[2][2]);
+ rfYAngle = (float) G3D::aTan2( -elt[2][0], elt[2][2]);
return true;
} else {
// WARNING. Not unique. ZA - YA = -atan(r02,r00)
- rfZAngle = -G3D::aTan2(elt[0][2], elt[0][0]);
+ rfZAngle = -(float)G3D::aTan2(elt[0][2], elt[0][0]);
rfXAngle = -(float)halfPi();
rfYAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. ZA + YA = atan2(r02,r00)
- rfZAngle = G3D::aTan2(elt[0][2], elt[0][0]);
+ rfZAngle = (float)G3D::aTan2(elt[0][2], elt[0][0]);
rfXAngle = (float)halfPi();
rfYAngle = 0.0f;
return false;
@@ -1525,19 +1534,19 @@ bool Matrix3::toEulerAnglesZYX (float& rfZAngle, float& rfYAngle,
if ( elt[2][0] < 1.0 ) {
if ( elt[2][0] > -1.0 ) {
rfZAngle = atan2f(elt[1][0], elt[0][0]);
- rfYAngle = asinf(-(double)elt[2][1]);
+ rfYAngle = asinf(-elt[2][0]);
rfXAngle = atan2f(elt[2][1], elt[2][2]);
return true;
} else {
// WARNING. Not unique. ZA - XA = -atan2(r01,r02)
- rfZAngle = -G3D::aTan2(elt[0][1], elt[0][2]);
+ rfZAngle = -(float)G3D::aTan2(elt[0][1], elt[0][2]);
rfYAngle = (float)halfPi();
rfXAngle = 0.0f;
return false;
}
} else {
// WARNING. Not unique. ZA + XA = atan2(-r01,-r02)
- rfZAngle = G3D::aTan2( -elt[0][1], -elt[0][2]);
+ rfZAngle = (float)G3D::aTan2( -elt[0][1], -elt[0][2]);
rfYAngle = -(float)halfPi();
rfXAngle = 0.0f;
return false;
@@ -1693,10 +1702,10 @@ void Matrix3::tridiagonal (float afDiag[3], float afSubDiag[3]) {
if ( G3D::abs(fC) >= EPSILON ) {
float fLength = sqrt(fB * fB + fC * fC);
- float fInvLength = 1.0 / fLength;
+ float fInvLength = 1.0f / fLength;
fB *= fInvLength;
fC *= fInvLength;
- float fQ = 2.0 * fB * fE + fC * (fF - fD);
+ float fQ = 2.0f * fB * fE + fC * (fF - fD);
afDiag[1] = fD + fC * fQ;
afDiag[2] = fF - fC * fQ;
afSubDiag[0] = fLength;
@@ -1732,16 +1741,16 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
// QL iteration with implicit shifting to reduce matrix from tridiagonal
// to diagonal
- for (int i0 = 0; i0 < 3; i0++) {
+ for (int i0 = 0; i0 < 3; ++i0) {
const int iMaxIter = 32;
int iIter;
- for (iIter = 0; iIter < iMaxIter; iIter++) {
+ for (iIter = 0; iIter < iMaxIter; ++iIter) {
int i1;
- for (i1 = i0; i1 <= 1; i1++) {
- float fSum = G3D::abs(afDiag[i1]) +
- G3D::abs(afDiag[i1 + 1]);
+ for (i1 = i0; i1 <= 1; ++i1) {
+ float fSum = float(G3D::abs(afDiag[i1]) +
+ G3D::abs(afDiag[i1 + 1]));
if ( G3D::abs(afSubDiag[i1]) + fSum == fSum )
break;
@@ -1750,9 +1759,9 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
if ( i1 == i0 )
break;
- float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0 * afSubDiag[i0]);
+ float fTmp0 = (afDiag[i0 + 1] - afDiag[i0]) / (2.0f * afSubDiag[i0]);
- float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0);
+ float fTmp1 = sqrt(fTmp0 * fTmp0 + 1.0f);
if ( fTmp0 < 0.0 )
fTmp0 = afDiag[i1] - afDiag[i0] + afSubDiag[i0] / (fTmp0 - fTmp1);
@@ -1771,25 +1780,25 @@ bool Matrix3::qLAlgorithm (float afDiag[3], float afSubDiag[3]) {
if (G3D::abs(fTmp3) >= G3D::abs(fTmp0)) {
fCos = fTmp0 / fTmp3;
- fTmp1 = sqrt(fCos * fCos + 1.0);
+ fTmp1 = sqrt(fCos * fCos + 1.0f);
afSubDiag[i2 + 1] = fTmp3 * fTmp1;
- fSin = 1.0 / fTmp1;
+ fSin = 1.0f / fTmp1;
fCos *= fSin;
} else {
fSin = fTmp3 / fTmp0;
- fTmp1 = sqrt(fSin * fSin + 1.0);
+ fTmp1 = sqrt(fSin * fSin + 1.0f);
afSubDiag[i2 + 1] = fTmp0 * fTmp1;
- fCos = 1.0 / fTmp1;
+ fCos = 1.0f / fTmp1;
fSin *= fCos;
}
fTmp0 = afDiag[i2 + 1] - fTmp2;
- fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0 * fTmp4 * fCos;
+ fTmp1 = (afDiag[i2] - fTmp0) * fSin + 2.0f * fTmp4 * fCos;
fTmp2 = fSin * fTmp1;
afDiag[i2 + 1] = fTmp0 + fTmp2;
fTmp0 = fCos * fTmp1 - fTmp4;
- for (int iRow = 0; iRow < 3; iRow++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
fTmp3 = elt[iRow][i2 + 1];
elt[iRow][i2 + 1] = fSin * elt[iRow][i2] +
fCos * fTmp3;
@@ -1820,7 +1829,7 @@ void Matrix3::eigenSolveSymmetric (float afEigenvalue[3],
kMatrix.tridiagonal(afEigenvalue, afSubDiag);
kMatrix.qLAlgorithm(afEigenvalue, afSubDiag);
- for (int i = 0; i < 3; i++) {
+ for (int i = 0; i < 3; ++i) {
akEigenvector[i][0] = kMatrix[0][i];
akEigenvector[i][1] = kMatrix[1][i];
akEigenvector[i][2] = kMatrix[2][i];
@@ -1841,8 +1850,8 @@ void Matrix3::eigenSolveSymmetric (float afEigenvalue[3],
//----------------------------------------------------------------------------
void Matrix3::tensorProduct (const Vector3& rkU, const Vector3& rkV,
Matrix3& rkProduct) {
- for (int iRow = 0; iRow < 3; iRow++) {
- for (int iCol = 0; iCol < 3; iCol++) {
+ for (int iRow = 0; iRow < 3; ++iRow) {
+ for (int iCol = 0; iCol < 3; ++iCol) {
rkProduct[iRow][iCol] = rkU[iRow] * rkV[iCol];
}
}
@@ -1922,9 +1931,9 @@ void Matrix3::_transpose(const Matrix3& A, Matrix3& out) {
//-----------------------------------------------------------------------------
std::string Matrix3::toString() const {
return G3D::format("[%g, %g, %g; %g, %g, %g; %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2],
- elt[1][0], elt[1][1], elt[1][2],
- elt[2][0], elt[2][1], elt[2][2]);
+ elt[0][0], elt[0][1], elt[0][2],
+ elt[1][0], elt[1][1], elt[1][2],
+ elt[2][0], elt[2][1], elt[2][2]);
}
diff --git a/dep/g3dlite/source/Matrix4.cpp b/dep/g3dlite/source/Matrix4.cpp
index fbc918f8f3e..f3b25ad5837 100644
--- a/dep/g3dlite/source/Matrix4.cpp
+++ b/dep/g3dlite/source/Matrix4.cpp
@@ -1,16 +1,16 @@
/**
- @file Matrix4.cpp
+ \file G3D/source/Matrix4.cpp
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-10-02
- @edited 2010-01-29
+ \created 2003-10-02
+ \edited 2012-02-19
*/
#include "G3D/platform.h"
#include "G3D/Matrix4.h"
#include "G3D/Matrix3.h"
+#include "G3D/Matrix2.h"
#include "G3D/Vector4.h"
#include "G3D/Vector3.h"
#include "G3D/BinaryInput.h"
@@ -24,11 +24,11 @@ namespace G3D {
Matrix4::Matrix4(const Any& any) {
- any.verifyName("Matrix4");
+ any.verifyNameBeginsWith("Matrix4", "CFrame", "CoordinateFrame");
any.verifyType(Any::ARRAY);
- const std::string& name = toLower(any.name());
- if (name == "matrix4") {
+ const std::string& name = any.name();
+ if (name == "Matrix4") {
any.verifySize(16);
for (int r = 0; r < 4; ++r) {
@@ -36,26 +36,43 @@ Matrix4::Matrix4(const Any& any) {
elt[r][c] = any[r * 4 + c];
}
}
- } else if (name == "matrix4::scale") {
+ } else if (name == "Matrix4::scale") {
if (any.size() == 1) {
- *this = scale(any[0].number());
+ *this = scale(any[0].floatValue());
} else if (any.size() == 3) {
*this = scale(any[0], any[1], any[2]);
} else {
any.verify(false, "Matrix4::scale() takes either 1 or 3 arguments");
}
- } else if (name == "matrix4::translation") {
+ } else if (name == "Matrix4::rollDegrees") {
+ any.verifySize(1);
+ *this = rollDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::yawDegrees") {
+ any.verifySize(1);
+ *this = yawDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::pitchDegrees") {
+ any.verifySize(1);
+ *this = pitchDegrees(any[0].floatValue());
+ } else if (name == "Matrix4::translation") {
if (any.size() == 3) {
*this = translation(any[0], any[1], any[2]);
} else {
- any.verify(false, "Matrix4::translation() takes either 1 or 3 arguments");
- } } else {
+ any.verify(false, "Matrix4::translation() requires 3 arguments");
+ }
+ } else if (name == "Matrix4::diagonal") {
+ any.verifySize(4);
+ *this = diagonal(any[0], any[1], any[2], any[3]);
+ } else if (name == "Matrix4::identity") {
+ *this = identity();
+ } else if (beginsWith(name, "CFrame") || beginsWith(name, "CoordinateFrame")) {
+ *this = CFrame(any);
+ } else {
any.verify(false, "Expected Matrix4 constructor");
}
}
-Matrix4::operator Any() const {
+Any Matrix4::toAny() const {
Any any(Any::ARRAY, "Matrix4");
any.resize(16);
for (int r = 0; r < 4; ++r) {
@@ -121,6 +138,12 @@ Matrix3 Matrix4::upper3x3() const {
}
+Matrix2 Matrix4::upper2x2() const {
+ return Matrix2(elt[0][0], elt[0][1],
+ elt[1][0], elt[1][1]);
+}
+
+
Matrix4 Matrix4::orthogonalProjection(
const class Rect2D& rect,
float nearval,
@@ -164,59 +187,59 @@ Matrix4 Matrix4::orthogonalProjection(
Matrix4 Matrix4::perspectiveProjection(
- float left,
- float right,
- float bottom,
- float top,
- float nearval,
- float farval,
- float upDirection) {
-
- float x, y, a, b, c, d;
-
- x = (2.0f*nearval) / (right-left);
- y = (2.0f*nearval) / (top-bottom);
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
a = (right+left) / (right-left);
b = (top+bottom) / (top-bottom);
- if (farval >= finf()) {
+ if (farval >= inf()) {
// Infinite view frustum
- c = -1.0f;
- d = -2.0f * nearval;
+ c = -1.0;
+ d = -2.0 * nearval;
} else {
c = -(farval+nearval) / (farval-nearval);
- d = -(2.0f*farval*nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
}
- debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
y *= upDirection;
b *= upDirection;
return Matrix4(
- x, 0, a, 0,
- 0, y, b, 0,
- 0, 0, c, d,
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
0, 0, -1, 0);
}
void Matrix4::getPerspectiveProjectionParameters(
- float& left,
- float& right,
- float& bottom,
- float& top,
- float& nearval,
- float& farval,
+ double& left,
+ double& right,
+ double& bottom,
+ double& top,
+ double& nearval,
+ double& farval,
float upDirection) const {
debugAssertM(abs(upDirection) == 1.0f, "upDirection must be -1 or +1");
- float x = elt[0][0];
- float y = elt[1][1] * upDirection;
- float a = elt[0][2];
- float b = elt[1][2] * upDirection;
- float c = elt[2][2];
- float d = elt[2][3];
+ double x = elt[0][0];
+ double y = elt[1][1] * upDirection;
+ double a = elt[0][2];
+ double b = elt[1][2] * upDirection;
+ double c = elt[2][2];
+ double d = elt[2][3];
// Verify that this really is a projection matrix
debugAssertM(elt[3][2] == -1, "Not a projection matrix");
@@ -232,18 +255,18 @@ void Matrix4::getPerspectiveProjectionParameters(
if (c == -1) {
farval = finf();
- nearval = -d / 2.0f;
+ nearval = -d / 2.0;
} else {
- nearval = d * ((c - 1.0f) / (c + 1.0f) - 1.0f) / (-2.0f * (c - 1.0f) / (c + 1.0f));
- farval = nearval * ((c - 1.0f) / (c + 1.0f));
+ nearval = d * ((c - 1.0) / (c + 1.0) - 1.0) / (-2.0 * (c - 1.0) / (c + 1.0));
+ farval = nearval * ((c - 1.0) / (c + 1.0));
}
- left = (a - 1.0f) * nearval / x;
- right = 2.0f * nearval / x + left;
+ left = (a - 1.0) * nearval / x;
+ right = 2.0 * nearval / x + left;
- bottom = (b - 1.0f) * nearval / y;
- top = 2.0f * nearval / y + bottom;
+ bottom = (b - 1.0) * nearval / y;
+ top = 2.0 * nearval / y + bottom;
}
@@ -401,7 +424,7 @@ bool Matrix4::operator==(const Matrix4& other) const {
float Matrix4::determinant() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- return cofactor().row(0).dot(row(0));
+ return cofactor().row(0).dot(row(0));
}
@@ -417,14 +440,14 @@ Matrix4 Matrix4::inverse() const {
// Determinant is the dot product of the first row and the first row
// of cofactors (i.e. the first col of the adjoint matrix)
- float det = A.column(0).dot(row(0));
+ float det = A.column(0).dot(row(0));
- return A * (1.0f / det);
+ return A * (1.0f / det);
}
Matrix4 Matrix4::cofactor() const {
- Matrix4 out;
+ Matrix4 out;
// We'll use i to incrementally compute -1 ^ (r+c)
int i = 1;
@@ -482,19 +505,19 @@ float Matrix4::subDeterminant(int excludeRow, int excludeCol) const {
CoordinateFrame Matrix4::approxCoordinateFrame() const {
- CoordinateFrame cframe;
+ CoordinateFrame cframe;
- for (int r = 0; r < 3; ++r) {
- for (int c = 0; c < 3; ++c) {
- cframe.rotation[r][c] = elt[r][c];
- }
- cframe.translation[r] = elt[r][3];
- }
+ for (int r = 0; r < 3; ++r) {
+ for (int c = 0; c < 3; ++c) {
+ cframe.rotation[r][c] = elt[r][c];
+ }
+ cframe.translation[r] = elt[r][3];
+ }
- // Ensure that the rotation matrix is orthonormal
- cframe.rotation.orthonormalize();
+ // Ensure that the rotation matrix is orthonormal
+ cframe.rotation.orthonormalize();
- return cframe;
+ return cframe;
}
@@ -517,12 +540,138 @@ void Matrix4::deserialize(class BinaryInput& b) {
std::string Matrix4::toString() const {
return G3D::format("[%g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g; %g, %g, %g, %g]",
- elt[0][0], elt[0][1], elt[0][2], elt[0][3],
- elt[1][0], elt[1][1], elt[1][2], elt[1][3],
- elt[2][0], elt[2][1], elt[2][2], elt[2][3],
- elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+ elt[0][0], elt[0][1], elt[0][2], elt[0][3],
+ elt[1][0], elt[1][1], elt[1][2], elt[1][3],
+ elt[2][0], elt[2][1], elt[2][2], elt[2][3],
+ elt[3][0], elt[3][1], elt[3][2], elt[3][3]);
+}
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+Matrix4float64::Matrix4float64(const Matrix4& m) {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = m[r][c];
+ }
+ }
+}
+
+
+Matrix4float64::Matrix4float64() {
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ elt[r][c] = 0.0;
+ }
+ }
+}
+
+
+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) {
+ elt[0][0] = r1c1; elt[0][1] = r1c2; elt[0][2] = r1c3; elt[0][3] = r1c4;
+ elt[1][0] = r2c1; elt[1][1] = r2c2; elt[1][2] = r2c3; elt[1][3] = r2c4;
+ elt[2][0] = r3c1; elt[2][1] = r3c2; elt[2][2] = r3c3; elt[2][3] = r3c4;
+ elt[3][0] = r4c1; elt[3][1] = r4c2; elt[3][2] = r4c3; elt[3][3] = r4c4;
+}
+
+
+const Matrix4float64& Matrix4float64::identity() {
+ static Matrix4float64 m(
+ 1, 0, 0, 0,
+ 0, 1, 0, 0,
+ 0, 0, 1, 0,
+ 0, 0, 0, 1);
+ return m;
+}
+
+
+const Matrix4float64& Matrix4float64::zero() {
+ static Matrix4float64 m;
+ return m;
+}
+
+
+bool Matrix4float64::operator!=(const Matrix4float64& other) const {
+ return ! (*this == other);
+}
+
+
+bool Matrix4float64::operator==(const Matrix4float64& other) const {
+
+ // If the bit patterns are identical, they must be
+ // the same matrix. If not, they *might* still have
+ // equal elements due to floating point weirdness.
+ if (memcmp(this, &other, sizeof(Matrix4float64) == 0)) {
+ return true;
+ }
+
+ for (int r = 0; r < 4; ++r) {
+ for (int c = 0; c < 4; ++c) {
+ if (elt[r][c] != other.elt[r][c]) {
+ return false;
+ }
+ }
+ }
+
+ return true;
}
+
+Vector4 Matrix4float64::operator*(const Vector4& vector) const {
+ Vector4 result;
+ for (int r = 0; r < 4; ++r) {
+ double sum = 0;
+ for (int c = 0; c < 4; ++c) {
+ sum += elt[r][c] * vector[c];
+ }
+ result[r] = (float)sum;
+ }
+
+ return result;
+}
+
+
+Matrix4float64 Matrix4float64::perspectiveProjection(
+ double left,
+ double right,
+ double bottom,
+ double top,
+ double nearval,
+ double farval,
+ float upDirection) {
+ double x, y, a, b, c, d;
+
+ x = (2.0*nearval) / (right-left);
+ y = (2.0*nearval) / (top-bottom);
+ a = (right+left) / (right-left);
+ b = (top+bottom) / (top-bottom);
+
+ if (farval >= inf()) {
+ // Infinite view frustum
+ c = -1.0;
+ d = -2.0 * nearval;
+ } else {
+ c = -(farval+nearval) / (farval-nearval);
+ d = -(2.0*farval*nearval) / (farval-nearval);
+ }
+
+ debugAssertM(abs(upDirection) == 1.0, "upDirection must be -1 or +1");
+ y *= upDirection;
+ b *= upDirection;
+
+ return Matrix4float64(
+ (float)x, 0, (float)a, 0,
+ 0, (float)y, (float)b, 0,
+ 0, 0, (float)c, (float)d,
+ 0, 0, -1, 0);
+}
+
+
} // namespace
diff --git a/dep/g3dlite/source/MemoryManager.cpp b/dep/g3dlite/source/MemoryManager.cpp
index 240188a1f0e..7346b0f0706 100644
--- a/dep/g3dlite/source/MemoryManager.cpp
+++ b/dep/g3dlite/source/MemoryManager.cpp
@@ -33,7 +33,7 @@ bool MemoryManager::isThreadsafe() const {
MemoryManager::Ref MemoryManager::create() {
- static MemoryManager::Ref m = new MemoryManager();
+ static MemoryManager::Ref m(new MemoryManager());
return m;
}
@@ -59,7 +59,7 @@ bool AlignedMemoryManager::isThreadsafe() const {
AlignedMemoryManager::Ref AlignedMemoryManager::create() {
- static AlignedMemoryManager::Ref m = new AlignedMemoryManager();
+ static AlignedMemoryManager::Ref m(new AlignedMemoryManager());
return m;
}
@@ -85,7 +85,7 @@ bool CRTMemoryManager::isThreadsafe() const {
CRTMemoryManager::Ref CRTMemoryManager::create() {
- static CRTMemoryManager::Ref m = new CRTMemoryManager();
+ static CRTMemoryManager::Ref m(new CRTMemoryManager());
return m;
}
}
diff --git a/dep/g3dlite/source/MeshAlg.cpp b/dep/g3dlite/source/MeshAlg.cpp
index 626fed92920..75dee727464 100644
--- a/dep/g3dlite/source/MeshAlg.cpp
+++ b/dep/g3dlite/source/MeshAlg.cpp
@@ -50,7 +50,7 @@ void MeshAlg::generateGrid(
texCoord.append(t);
- if (height.notNull()) {
+ if (height) {
v.y = height->nearest(v.x * (height->width() - 1), v.z * (height->height() - 1)).value;
}
if (spaceCentered) {
@@ -253,7 +253,7 @@ void MeshAlg::identifyBackfaces(
backface.resize(faceArray.size());
- if (fuzzyEq(HP.w, 0.0)) {
+ if (fuzzyEq(HP.w, 0.0f)) {
// Infinite case
for (int f = faceArray.size() - 1; f >= 0; --f) {
const MeshAlg::Face& face = faceArray[f];
@@ -294,7 +294,7 @@ void MeshAlg::identifyBackfaces(
backface.resize(faceArray.size());
- if (fuzzyEq(HP.w, 0.0)) {
+ if (fuzzyEq(HP.w, 0.0f)) {
// Infinite case
for (int f = faceArray.size() - 1; f >= 0; --f) {
const Vector3& N = faceNormals[f];
@@ -417,6 +417,7 @@ void MeshAlg::computeBounds(
AABox& box,
Sphere& sphere) {
+ // Makes a copy so as to re-use the existing computebounds code
Array<Vector3> newArray;
newArray.resize(indexArray.size());
for (int i = 0; i < indexArray.size(); ++i) {
@@ -441,54 +442,54 @@ void MeshAlg::computeBounds(
const Vector3& vertex = vertexArray[v];
if (vertex.x < xmin.x) {
- xmin = vertex;
+ xmin = vertex;
}
if (vertex.x > xmax.x) {
- xmax = vertex;
+ xmax = vertex;
}
if (vertex.y < ymin.y) {
- ymin = vertex;
+ ymin = vertex;
}
if (vertex.y > ymax.y) {
- ymax = vertex;
+ ymax = vertex;
}
if (vertex.z < zmin.z) {
- zmin = vertex;
+ zmin = vertex;
}
if (vertex.z > zmax.z) {
- zmax = vertex;
+ zmax = vertex;
}
- }
+ }
// Set points dia1 & dia2 to the maximally separated pair
Vector3 dia1 = xmin;
Vector3 dia2 = xmax;
{
// Set xspan = distance between the 2 points xmin & xmax (squared)
- double xspan = (xmax - xmin).squaredMagnitude();
+ float xspan = (xmax - xmin).squaredMagnitude();
// Same for y & z spans
- double yspan = (ymax - ymin).squaredMagnitude();
- double zspan = (zmax - zmin).squaredMagnitude();
+ float yspan = (ymax - ymin).squaredMagnitude();
+ float zspan = (zmax - zmin).squaredMagnitude();
- double maxspan = xspan;
+ float maxspan = xspan;
if (yspan > maxspan) {
- maxspan = yspan;
- dia1 = ymin;
+ maxspan = yspan;
+ dia1 = ymin;
dia2 = ymax;
- }
+ }
if (zspan > maxspan) {
maxspan = zspan;
- dia1 = zmin;
+ dia1 = zmin;
dia2 = zmax;
- }
+ }
}
@@ -500,52 +501,52 @@ void MeshAlg::computeBounds(
// calculate initial radius^2 and radius
Vector3 d = dia2 - sphere.center;
- double radSq = d.squaredMagnitude();
- double rad = sqrt(radSq);
+ float radSq = d.squaredMagnitude();
+ float rad = sqrt(radSq);
// SECOND PASS: increment current sphere
- double old_to_p, old_to_new;
+ float old_to_p, old_to_new;
for (int v = 0; v < vertexArray.size(); ++v) {
const Vector3& vertex = vertexArray[v];
d = vertex - center;
- double old_to_p_sq = d.squaredMagnitude();
+ float old_to_p_sq = d.squaredMagnitude();
- // do r^2 test first
+ // do r^2 test first
if (old_to_p_sq > radSq) {
- // this point is outside of current sphere
- old_to_p = sqrt(old_to_p_sq);
+ // this point is outside of current sphere
+ old_to_p = sqrt(old_to_p_sq);
- // calc radius of new sphere
- rad = (rad + old_to_p) / 2.0;
+ // calc radius of new sphere
+ rad = (rad + old_to_p) / 2.0f;
// for next r^2 compare
- radSq = rad * rad;
- old_to_new = old_to_p - rad;
+ radSq = rad * rad;
+ old_to_new = old_to_p - rad;
- // calc center of new sphere
+ // calc center of new sphere
center = (rad * center + old_to_new * vertex) / old_to_p;
- }
- }
+ }
+ }
- const Vector3 min(xmin.x, ymin.y, zmin.z);
- const Vector3 max(xmax.x, ymax.y, zmax.z);
+ const Vector3 min(xmin.x, ymin.y, zmin.z);
+ const Vector3 max(xmax.x, ymax.y, zmax.z);
- box = AABox(min, max);
+ box = AABox(min, max);
- const float boxRadSq = (max - min).squaredMagnitude() * 0.25f;
+ const float boxRadSq = (max - min).squaredMagnitude() * 0.25f;
- if (boxRadSq >= radSq){
- if (isNaN(center.x) || ! isFinite(rad)) {
- sphere = Sphere(Vector3::zero(), finf());
- } else {
- sphere = Sphere(center, rad);
- }
- } else {
- sphere = Sphere((max + min) * 0.5f, sqrt(boxRadSq));
- }
+ if (boxRadSq >= radSq){
+ if (isNaN(center.x) || ! isFinite(rad)) {
+ sphere = Sphere(Vector3::zero(), finf());
+ } else {
+ sphere = Sphere(center, rad);
+ }
+ } else {
+ sphere = Sphere((max + min) * 0.5f, sqrt(boxRadSq));
+ }
}
void MeshAlg::computeTangentSpaceBasis(
@@ -600,7 +601,10 @@ void MeshAlg::computeTangentSpaceBasis(
float r = te1.x * te2.y - te1.y * te2.x;
if (r == 0.0) {
// degenerate case
- Vector3::generateOrthonormalBasis(t, b, n, true);
+ if (! n.isFinite() || n.isZero()) {
+ n = Vector3::unitY();
+ }
+ n.getTangents(t, b);
} else {
r = 1.0f / r;
t = (te2.y * ve1 - te1.y * ve2) * r;
diff --git a/dep/g3dlite/source/MeshAlgAdjacency.cpp b/dep/g3dlite/source/MeshAlgAdjacency.cpp
index f0bf3382131..e3bdbd635e1 100644
--- a/dep/g3dlite/source/MeshAlgAdjacency.cpp
+++ b/dep/g3dlite/source/MeshAlgAdjacency.cpp
@@ -5,7 +5,7 @@
@created 2003-09-14
@edited 2010-04-26
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -125,6 +125,11 @@ public:
return *this;
}
+ bool isValid() const {
+ return ! m_end;
+ }
+
+ /** @deprecated Use isValid */
bool hasMore() const {
return ! m_end;
}
@@ -254,7 +259,7 @@ void MeshAlg::computeAdjacency(
MeshEdgeTable::Iterator cur = edgeTable.begin();
Array<Edge> tempEdgeArray;
- while (cur.hasMore()) {
+ while (cur.isValid()) {
MeshEdgeTable::FaceIndexArray& faceIndexArray = cur.faceIndex();
// Process this edge
@@ -620,7 +625,7 @@ void MeshAlg::weldAdjacency(
Array<Face>& faceArray,
Array<Edge>& edgeArray,
Array<Vertex>& vertexArray,
- double radius) {
+ float radius) {
// Num vertices
const int n = originalGeometry.size();
diff --git a/dep/g3dlite/source/MeshAlgWeld.cpp b/dep/g3dlite/source/MeshAlgWeld.cpp
index 6067f17c2fb..b1e602f9566 100644
--- a/dep/g3dlite/source/MeshAlgWeld.cpp
+++ b/dep/g3dlite/source/MeshAlgWeld.cpp
@@ -40,18 +40,18 @@ public:
Array<int>& toOld;
/** Must be less than one grid cell, not checked */
- const double radius;
+ const float radius;
/** (oldVertexArray[i] - offset) * scale is on the range [0, 1] */
Vector3 offset;
Vector3 scale;
- Welder(
- const Array<Vector3>& _oldVertexArray,
- Array<Vector3>& _newVertexArray,
- Array<int>& _toNew,
- Array<int>& _toOld,
- double _radius);
+ Welder
+ (const Array<Vector3>& _oldVertexArray,
+ Array<Vector3>& _newVertexArray,
+ Array<int>& _toNew,
+ Array<int>& _toOld,
+ float _radius);
/**
Computes the grid index from an ordinate.
@@ -73,6 +73,7 @@ template<> struct HashTrait<G3D::_internal::Welder::List*> {
static size_t hashCode(const G3D::_internal::Welder::List* key) { return reinterpret_cast<size_t>(key); }
};
+
namespace G3D {
namespace _internal {
@@ -81,7 +82,7 @@ Welder::Welder(
Array<Vector3>& _newVertexArray,
Array<int>& _toNew,
Array<int>& _toOld,
- double _radius) :
+ float _radius) :
oldVertexArray(_oldVertexArray),
newVertexArray(_newVertexArray),
toNew(_toNew),
@@ -102,10 +103,10 @@ Welder::Welder(
scale = maxBound - minBound;
for (int i = 0; i < 3; ++i) {
// The model might have zero extent along some axis
- if (fuzzyEq(scale[i], 0.0)) {
+ if (fuzzyEq(scale[i], 0.0f)) {
scale[i] = 1.0;
} else {
- scale[i] = 1.0 / scale[i];
+ scale[i] = 1.0f / scale[i];
}
}
}
@@ -204,10 +205,10 @@ void MeshAlg::computeWeld(
Array<Vector3>& newVertexArray,
Array<int>& toNew,
Array<int>& toOld,
- double radius) {
+ float radius) {
- _internal::Welder welder(oldVertexArray, newVertexArray, toNew, toOld, radius);
- welder.weld();
+ shared_ptr<_internal::Welder> welder = shared_ptr<_internal::Welder> (new _internal::Welder(oldVertexArray, newVertexArray, toNew, toOld, radius));
+ welder->weld();
}
} // G3D namespace
diff --git a/dep/g3dlite/source/MeshBuilder.cpp b/dep/g3dlite/source/MeshBuilder.cpp
index 1bf2bab5d1c..6109af94697 100644
--- a/dep/g3dlite/source/MeshBuilder.cpp
+++ b/dep/g3dlite/source/MeshBuilder.cpp
@@ -36,7 +36,7 @@ void MeshBuilder::commit(std::string& n, Array<int>& indexArray, Array<Vector3>&
close = minEdgeLen * 0.1;
}
- MeshAlg::computeWeld(triList, outvertexArray, toNew, toOld, close);
+ MeshAlg::computeWeld(triList, outvertexArray, toNew, toOld, (float)close);
// Construct triangles
for (int t = 0; t < triList.size(); t += 3) {
@@ -62,19 +62,21 @@ void MeshBuilder::centerTriList() {
computeBounds(vmin, vmax);
- Vector3 diagonal = vmax - vmin;
- double scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2;
+ const Vector3 diagonal = vmax - vmin;
+ float scale = max(max(diagonal.x, diagonal.y), diagonal.z) / 2.0f;
debugAssert(scale > 0);
- Vector3 translation = vmin + diagonal / 2;
+ const Vector3 translation = vmin + diagonal / 2.0f;
// Center and scale all vertices in the input list
int v;
- //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90));
- for (v = 0; v < triList.size(); ++v) {
- triList[v] = (triList[v] - translation) / scale;
- //triList[v] = rot90 * triList[v];
+ if (scaleAndCenter) {
+ //Matrix3 rot90 = Matrix3::fromAxisAngle(Vector3::UNIT_Y, toRadians(180)) * Matrix3::fromAxisAngle(Vector3::UNIT_X, toRadians(90));
+ for (v = 0; v < triList.size(); ++v) {
+ triList[v] = (triList[v] - translation) / scale;
+ //triList[v] = rot90 * triList[v];
+ }
}
}
@@ -94,9 +96,9 @@ void MeshBuilder::computeBounds(Vector3& min, Vector3& max) {
void MeshBuilder::addTriangle(const Vector3& a, const Vector3& b, const Vector3& c) {
triList.append(a, b, c);
- if (_twoSided) {
- triList.append(c, b, a);
- }
+ if (_twoSided) {
+ triList.append(c, b, a);
+ }
}
@@ -107,7 +109,7 @@ void MeshBuilder::addQuad(const Vector3& a, const Vector3& b, const Vector3& c,
void MeshBuilder::addTriangle(const Triangle& t) {
- addTriangle(t.vertex(0), t.vertex(1), t.vertex(2));
+ addTriangle(t.vertex(0), t.vertex(1), t.vertex(2));
}
} // namespace
diff --git a/dep/g3dlite/source/NetAddress.cpp b/dep/g3dlite/source/NetAddress.cpp
index 64d692d4763..95f975b0ca0 100644
--- a/dep/g3dlite/source/NetAddress.cpp
+++ b/dep/g3dlite/source/NetAddress.cpp
@@ -1,9 +1,9 @@
/**
- @file NetMessage.cpp
+ \file NetAddress.cpp
- @maintainer Morgan McGuire, morgan@cs.brown.edu
- @created 2005-02-06
- @edited 2005-02-06
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2005-02-06
+ \edited 2013-03-17
*/
#include "G3D/platform.h"
#include "G3D/NetAddress.h"
@@ -13,6 +13,7 @@
#include "G3D/stringutils.h"
#include "G3D/System.h"
#include "G3D/NetworkDevice.h"
+#include "G3D/Log.h"
#if defined(G3D_LINUX) || defined(G3D_OSX)
#include <unistd.h>
@@ -23,6 +24,7 @@
#include <netdb.h>
#include <netinet/tcp.h>
#define _alloca alloca
+ #define SOCKET_ERROR -1
# ifndef SOCKADDR_IN
# define SOCKADDR_IN struct sockaddr_in
@@ -40,6 +42,7 @@
namespace G3D {
+
NetAddress::NetAddress() {
System::memset(&addr, 0, sizeof(addr));
}
@@ -58,15 +61,15 @@ void NetAddress::init(uint32 host, uint16 port) {
}
-NetAddress::NetAddress(
- const std::string& hostname,
+NetAddress::NetAddress
+ (const std::string& hostname,
uint16 port) {
init(hostname, port);
}
-void NetAddress::init(
- const std::string& hostname,
+void NetAddress::init
+ (const std::string& hostname,
uint16 port) {
uint32 addr;
@@ -77,7 +80,7 @@ void NetAddress::init(
addr = inet_addr(hostname.c_str());
}
- // The address wasn't in numeric form, resolve it
+ // The address wasn't in numeric form, resolve it
if (addr == INADDR_NONE) {
// Get the IP address of the server and store it in host
struct hostent* host = gethostbyname(hostname.c_str());
@@ -122,13 +125,35 @@ NetAddress::NetAddress(const SOCKADDR_IN& a) {
NetAddress::NetAddress(const struct in_addr& addr, uint16 port) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
init(ntohl(addr.S_un.S_addr), port);
#else
init(htonl(addr.s_addr), port);
#endif
}
+void NetAddress::localHostAddresses(Array<NetAddress>& array) {
+ array.resize(0);
+
+ char ac[256];
+
+ if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
+ Log::common()->printf("Error while getting local host name\n");
+ return;
+ }
+
+ struct hostent* phe = gethostbyname(ac);
+ if (phe == 0) {
+ Log::common()->printf("Error while getting local host address\n");
+ return;
+ }
+
+ for (int i = 0; (phe->h_addr_list[i] != 0); ++i) {
+ struct in_addr addr;
+ memcpy(&addr, phe->h_addr_list[i], sizeof(struct in_addr));
+ array.append(NetAddress(addr));
+ }
+}
void NetAddress::serialize(class BinaryOutput& b) const {
b.writeUInt32(ip());
diff --git a/dep/g3dlite/source/NetworkDevice.cpp b/dep/g3dlite/source/NetworkDevice.cpp
index 1fc794479f5..e9d4f112c5a 100644
--- a/dep/g3dlite/source/NetworkDevice.cpp
+++ b/dep/g3dlite/source/NetworkDevice.cpp
@@ -31,19 +31,18 @@ std::ostream& operator<<(std::ostream& os, const NetAddress& a) {
static void logSocketInfo(const SOCKET& sock) {
uint32 val;
socklen_t sz = 4;
- int ret;
- ret = getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_RCVBUF, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_RCVBUF = %d\n", val);
- ret = getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_SNDBUF, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_SNDBUF = %d\n", val);
// Note: timeout = 0 means no timeout
- ret = getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_RCVTIMEO = %d\n", val);
- ret = getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, (socklen_t*)&sz);
+ getsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, (char*)&val, (socklen_t*)&sz);
logPrintf("SOL_SOCKET/SO_SNDTIMEO = %d\n", val);
}
@@ -63,7 +62,7 @@ static int selectOneReadSocket(const SOCKET& sock) {
FD_ZERO(&socketSet);
FD_SET(sock, &socketSet);
- int ret = select(sock + 1, &socketSet, NULL, NULL, &timeout);
+ int ret = select((int)sock + 1, &socketSet, NULL, NULL, &timeout);
return ret;
}
@@ -102,7 +101,7 @@ static int selectOneWriteSocket(const SOCKET& sock) {
FD_ZERO(&socketSet);
FD_SET(sock, &socketSet);
- return select(sock + 1, NULL, &socketSet, NULL, &timeout);
+ return select((int)sock + 1, NULL, &socketSet, NULL, &timeout);
}
///////////////////////////////////////////////////////////////////////////////
@@ -146,7 +145,7 @@ std::string NetworkDevice::localHostName() const {
return gethostbyname(ac)->h_name;
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
const char* errnoToString() {
switch (errno) {
case EBADF:
@@ -192,31 +191,31 @@ void NetworkDevice::EthernetAdapter::describe(TextOutput& t) const {
t.writeNewline();
t.writeSymbols("hostname", "=");
- t.writeString(hostname);
+ t.writeString(hostname + ";");
t.writeNewline();
t.writeSymbols("name", "=");
- t.writeString(name);
+ t.writeString(name + ";");
t.writeNewline();
t.writeSymbols("ip", "=");
- t.writeSymbol(formatIP(ip));
+ t.writeSymbol("\"" + formatIP(ip) + "\";");
t.writeNewline();
t.writeSymbols("subnet", "=");
- t.writeSymbol(formatIP(subnet));
+ t.writeSymbol("\"" + formatIP(subnet) + "\";");
t.writeNewline();
t.writeSymbols("broadcast", "=");
- t.writeSymbol(formatIP(broadcast));
+ t.writeSymbol("\"" + formatIP(broadcast) + "\";");
t.writeNewline();
t.writeSymbols("mac", "=");
- t.writeSymbol(formatMAC(mac));
+ t.writeSymbol("\"" + formatMAC(mac) + "\";");
t.writeNewline();
t.popIndent();
- t.writeSymbol("}");
+ t.writeSymbol("};");
t.writeNewline();
}
@@ -243,15 +242,17 @@ std::string NetworkDevice::formatMAC(const uint8 MAC[6]) {
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
bool NetworkDevice::init() {
debugAssert(! initialized);
logPrintf("Network Startup");
logPrintf("Starting WinSock networking.\n");
- WSADATA wsda;
- WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda);
+
+// G3D now initializes winsock through ENet
+// WSADATA wsda;
+// WSAStartup(MAKEWORD(G3D_WINSOCK_MAJOR_VERSION, G3D_WINSOCK_MINOR_VERSION), &wsda);
std::string hostname = "localhost";
{
@@ -280,7 +281,9 @@ bool NetworkDevice::init() {
std::string machine = localHostName();
std::string addr = NetAddress(machine, 0).ipString();
+ /*
logPrintf(
+
"Network:\n"
" Status: %s\n"
" Loaded winsock specification version %d (%d is "
@@ -293,6 +296,7 @@ bool NetworkDevice::init() {
wsda.wHighVersion,
wsda.iMaxSockets,
wsda.iMaxUdpDg);
+ */
// TODO: WSAIoctl for subnet and broadcast addresses
// http://msdn.microsoft.com/en-us/library/ms741621(VS.85).aspx
@@ -449,7 +453,7 @@ bool NetworkDevice::init() {
}
// Extract all interesting adapters from the table
- for (AdapterTable::Iterator it = table.begin(); it.hasMore(); ++it) {
+ for (AdapterTable::Iterator it = table.begin(); it.isValid(); ++it) {
const EthernetAdapter& adapter = it->value;
// Only add adapters that have IP addresses
@@ -471,11 +475,10 @@ bool NetworkDevice::init() {
void NetworkDevice::_cleanup() {
debugAssert(initialized);
- logPrintf("Network Cleanup");
-# ifdef G3D_WIN32
- WSACleanup();
+# ifdef G3D_WINDOWS
+ // Now handled through enet
+// WSACleanup();
# endif
- logPrintf("Network cleaned up.");
}
bool NetworkDevice::bind(SOCKET sock, const NetAddress& addr) const {
@@ -497,7 +500,7 @@ bool NetworkDevice::bind(SOCKET sock, const NetAddress& addr) const {
void NetworkDevice::closesocket(SOCKET& sock) const {
if (sock != 0) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
::closesocket(sock);
#else
close(sock);
@@ -512,7 +515,7 @@ void NetworkDevice::closesocket(SOCKET& sock) const {
void NetworkDevice::localHostAddresses(Array<NetAddress>& array) const {
array.resize(0);
- char ac[128];
+ char ac[256];
if (gethostname(ac, sizeof(ac)) == SOCKET_ERROR) {
Log::common()->printf("Error while getting local host name\n");
@@ -606,13 +609,16 @@ static void increaseBufferSize(SOCKET sock) {
//////////////////////////////////////////////////////////////////////////////
ReliableConduitRef ReliableConduit::create(const NetAddress& address) {
- return new ReliableConduit(address);
+ return ReliableConduitRef(new ReliableConduit(address));
}
-ReliableConduit::ReliableConduit(
- const NetAddress& _addr) : state(NO_MESSAGE), receiveBuffer(NULL),
- receiveBufferTotalSize(0), receiveBufferUsedSize(0) {
+ReliableConduit::ReliableConduit
+ (const NetAddress& _addr) :
+ state(NO_MESSAGE),
+ receiveBuffer(NULL),
+ receiveBufferTotalSize(0),
+ receiveBufferUsedSize(0) {
NetworkDevice* nd = NetworkDevice::instance();
@@ -829,7 +835,7 @@ uint32 ReliableConduit::waitingMessageType() {
void ReliableConduit::sendBuffer(const BinaryOutput& b) {
NetworkDevice* nd = NetworkDevice::instance();
- int ret = ::send(sock, (const char*)b.getCArray(), b.size(), 0);
+ int ret = ::send(sock, (const char*)b.getCArray(), (int)b.size(), 0);
if (ret == SOCKET_ERROR) {
Log::common()->println("Error occured while sending message.");
@@ -938,11 +944,11 @@ void ReliableConduit::receiveIntoBuffer() {
// Read the data itself
int ret = 0;
- uint32 left = messageSize - receiveBufferUsedSize;
+ uint32 left = messageSize - (uint32)receiveBufferUsedSize;
int count = 0;
while ((ret != SOCKET_ERROR) && (left > 0) && (count < 100)) {
- ret = recv(sock, ((char*)receiveBuffer) + receiveBufferUsedSize, left, 0);
+ ret = recv(sock, ((char*)receiveBuffer) + (uint32)receiveBufferUsedSize, left, 0);
if (ret > 0) {
left -= ret;
@@ -985,11 +991,12 @@ LightweightConduitRef LightweightConduit::create(
bool enableReceive,
bool enableBroadcast) {
- return new LightweightConduit(receivePort, enableReceive, enableBroadcast);
+ return LightweightConduitRef(new LightweightConduit(receivePort, enableReceive, enableBroadcast));
}
-LightweightConduit::LightweightConduit(
- uint16 port,
+
+LightweightConduit::LightweightConduit
+ (uint16 port,
bool enableReceive,
bool enableBroadcast) {
NetworkDevice* nd = NetworkDevice::instance();
@@ -1064,7 +1071,7 @@ bool LightweightConduit::receive(NetAddress& sender) {
void LightweightConduit::sendBuffer(const NetAddress& a, BinaryOutput& b) {
NetworkDevice* nd = NetworkDevice::instance();
- if (sendto(sock, (const char*)b.getCArray(), b.size(), 0,
+ if (sendto(sock, (const char*)b.getCArray(), (int)b.size(), 0,
(struct sockaddr *) &(a.addr), sizeof(a.addr)) == SOCKET_ERROR) {
Log::common()->printf("Error occured while sending packet "
"to %s\n", inet_ntoa(a.addr.sin_addr));
@@ -1137,7 +1144,7 @@ uint32 LightweightConduit::waitingMessageType() {
///////////////////////////////////////////////////////////////////////////////
NetListenerRef NetListener::create(const uint16 port) {
- return new NetListener(port);
+ return NetListenerRef(new NetListener(port));
}
@@ -1215,20 +1222,20 @@ ReliableConduitRef NetListener::waitForConnection() {
Log::common()->println("Error in NetListener::acceptConnection.");
Log::common()->println(socketErrorCode());
nd->closesocket(sock);
- return NULL;
+ return ReliableConduitRef();
}
Log::common()->printf("%s connected, transferred to socket %d.\n",
inet_ntoa(remote_addr.sin_addr), sClient);
- #ifndef G3D_WIN32
- return new ReliableConduit(sClient,
+ #ifndef G3D_WINDOWS
+ return ReliableConduitRef(new ReliableConduit(sClient,
NetAddress(htonl(remote_addr.sin_addr.s_addr),
- ntohs(remote_addr.sin_port)));
+ ntohs(remote_addr.sin_port))));
#else
- return new ReliableConduit(sClient,
+ return ReliableConduitRef(ReliableConduitRef(new ReliableConduit(sClient,
NetAddress(ntohl(remote_addr.sin_addr.S_un.S_addr),
- ntohs(remote_addr.sin_port)));
+ ntohs(remote_addr.sin_port)))));
#endif
}
@@ -1247,17 +1254,17 @@ bool NetListener::clientWaiting() const {
void NetworkDevice::describeSystem(
TextOutput& t) {
- t.writeSymbols("Network", "{");
+ t.writeSymbols("Network", "=", "{");
t.writeNewline();
t.pushIndent();
for (int i = 0; i < m_adapterArray.size(); ++i) {
+ t.printf("Adapter%d =", i);
m_adapterArray[i].describe(t);
}
-
t.popIndent();
- t.writeSymbols("}");
+ t.writeSymbols("};");
t.writeNewline();
t.writeNewline();
}
diff --git a/dep/g3dlite/source/PhysicsFrame.cpp b/dep/g3dlite/source/PhysicsFrame.cpp
index 30fbdf8d619..9146d78ff5b 100644
--- a/dep/g3dlite/source/PhysicsFrame.cpp
+++ b/dep/g3dlite/source/PhysicsFrame.cpp
@@ -1,10 +1,10 @@
/**
- @file PhysicsFrame.cpp
+ \file PhysicsFrame.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2002-07-09
- @edited 2010-03-25
+ \created 2002-07-09
+ \edited 2013-04-25
*/
#include "G3D/platform.h"
@@ -13,6 +13,7 @@
#include "G3D/PhysicsFrame.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/UprightFrame.h"
namespace G3D {
@@ -22,31 +23,44 @@ PhysicsFrame::PhysicsFrame() {
}
-PhysicsFrame::PhysicsFrame(
- const CoordinateFrame& coordinateFrame) {
-
+PhysicsFrame::PhysicsFrame
+ (const CoordinateFrame& coordinateFrame) {
translation = coordinateFrame.translation;
rotation = Quat(coordinateFrame.rotation);
}
+Any PhysicsFrame::toAny() const {
+ // Prefer to serialize as a CFrame, which is easier to read
+ if (false) {
+ Any a(Any::ARRAY, "PFrame");
+ a.append(rotation, translation.toAny("Point3"));
+ return a;
+ } else {
+ return CFrame(*this).toAny();
+ }
+}
+
+
PhysicsFrame::PhysicsFrame(const Any& a) {
const std::string& n = toLower(a.name());
*this = PhysicsFrame();
- if (beginsWith(n, "vector3")) {
- *this = PhysicsFrame(Vector3(a));
+ if (beginsWith(n, "vector3") || beginsWith(n, "point3")) {
+ *this = PhysicsFrame(Point3(a));
} else if (beginsWith(n, "matrix3")) {
*this = PhysicsFrame(Matrix3(a));
- } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe")) {
- *this = PhysicsFrame(CoordinateFrame(a));
+ } else if (beginsWith(n, "cframe") || beginsWith(n, "coordinateframe") || beginsWith(n, "matrix4")) {
+ *this = CoordinateFrame(a);
+ } else if (beginsWith(n, "uprightframe")) {
+ *this = UprightFrame(a).toCoordinateFrame();
} else if (beginsWith(n, "pframe") || beginsWith(n, "physicsframe")) {
if (a.type() == Any::ARRAY) {
a.verifySize(2);
rotation = a[0];
translation = a[1];
} else {
- for (Any::AnyTable::Iterator it = a.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = a.table().begin(); it.isValid(); ++it) {
const std::string& n = toLower(it->key);
if (n == "translation") {
translation = it->value;
@@ -57,6 +71,8 @@ PhysicsFrame::PhysicsFrame(const Any& a) {
}
}
}
+ } else {
+ a.verify(false, "Unrecognized class name where a PhysicsFrame or equivalent was expected.");
}
}
diff --git a/dep/g3dlite/source/PhysicsFrameSpline.cpp b/dep/g3dlite/source/PhysicsFrameSpline.cpp
index 2dfdb6f9139..ca9d6cc55d7 100644
--- a/dep/g3dlite/source/PhysicsFrameSpline.cpp
+++ b/dep/g3dlite/source/PhysicsFrameSpline.cpp
@@ -6,55 +6,53 @@
#include "G3D/PhysicsFrameSpline.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/UprightFrame.h"
namespace G3D {
PhysicsFrameSpline::PhysicsFrameSpline() {}
+
PhysicsFrameSpline::PhysicsFrameSpline(const Any& any) {
- *this = any;
+ if (beginsWith(any.name(), "PFrameSpline") ||
+ beginsWith(any.name(), "PhysicsFrameSpline") ||
+ beginsWith(any.name(), "CFrameSpline") ||
+ beginsWith(any.name(), "CoordinateFrameSpline") ||
+ beginsWith(any.name(), "UprightSpline") ||
+ beginsWith(any.name(), "UprightFrameSpline")) {
+ AnyTableReader t(any);
+ init(t);
+ t.verifyDone();
+ } else {
+ // Must be a single control point
+ control.append(any);
+ time.append(0);
+ }
}
-PhysicsFrameSpline& PhysicsFrameSpline::operator=(const Any& any) {
- const std::string& n = toLower(any.name());
- *this = PhysicsFrameSpline();
-
- if (n == "physicsframespline" || n == "pframespline") {
- any.verifyName("PhysicsFrameSpline", "PFrameSpline");
-
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
- const std::string& k = toLower(it->key);
- if (k == "cyclic") {
- cyclic = it->value;
- } else if (k == "control") {
- const Any& v = it->value;
- v.verifyType(Any::ARRAY);
- control.resize(v.size());
- for (int i = 0; i < control.size(); ++i) {
- control[i] = v[i];
- }
- if (! any.containsKey("time")) {
- time.resize(control.size());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = i;
- }
- }
- } else if (k == "finalinterval") {
- finalInterval = it->value;
- } else if (k == "time") {
- const Any& v = it->value;
- v.verifyType(Any::ARRAY);
- time.resize(v.size());
- for (int i = 0; i < time.size(); ++i) {
- time[i] = v[i];
- }
+
+bool PhysicsFrameSpline::operator==(const PhysicsFrameSpline& other) const {
+ if ((extrapolationMode == other.extrapolationMode) &&
+ (time.size() == other.size()) &&
+ (finalInterval == other.finalInterval) &&
+ (control.size() == other.control.size())) {
+ // Check actual values
+ for (int i = 0; i < time.size(); ++i) {
+ if (time[i] != other.time[i]) {
+ return false;
+ }
+ }
+
+ for (int i = 0; i < control.size(); ++i) {
+ if (control[i] != other.control[i]) {
+ return false;
}
}
+
+ return true;
} else {
- // Must be a PhysicsFrame constructor of some kind
- append(any);
+ return false;
}
- return *this;
}
@@ -62,6 +60,11 @@ void PhysicsFrameSpline::correct(PhysicsFrame& frame) const {
frame.rotation.unitize();
}
+void PhysicsFrameSpline::scaleControlPoints(float scaleFactor) {
+ for (int i = 0; i < control.size(); ++i) {
+ control[i].translation *= scaleFactor;
+ }
+}
void PhysicsFrameSpline::ensureShortestPath(PhysicsFrame* A, int N) const {
for (int i = 1; i < N; ++i) {
diff --git a/dep/g3dlite/source/Plane.cpp b/dep/g3dlite/source/Plane.cpp
index 9b7991c0333..d6b41d3605d 100644
--- a/dep/g3dlite/source/Plane.cpp
+++ b/dep/g3dlite/source/Plane.cpp
@@ -4,7 +4,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-02-06
- @edited 2006-01-29
+ \edited 2011-02-29
*/
#include "G3D/platform.h"
@@ -12,31 +12,47 @@
#include "G3D/BinaryOutput.h"
#include "G3D/BinaryInput.h"
#include "G3D/stringutils.h"
+#include "G3D/Any.h"
namespace G3D {
+Plane::Plane(const Any& a) {
+ a.verifyName("Plane");
+ a.verifySize(2);
+ a.verifyType(Any::ARRAY);
+ *this = Plane(Vector3(a[0]), Point3(a[1]));
+}
+
+
+Any Plane::toAny() const {
+ Any a(Any::ARRAY, "Plane");
+ a.append(normal(), normal() * _distance);
+ return a;
+}
+
+
Plane::Plane(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Plane::serialize(class BinaryOutput& b) const {
- _normal.serialize(b);
- b.writeFloat64(_distance);
+ _normal.serialize(b);
+ b.writeFloat64(_distance);
}
void Plane::deserialize(class BinaryInput& b) {
- _normal.deserialize(b);
- _distance = (float)b.readFloat64();
+ _normal.deserialize(b);
+ _distance = (float)b.readFloat64();
}
-Plane::Plane(
- Vector4 point0,
- Vector4 point1,
- Vector4 point2) {
-
+Plane::Plane
+(Vector4 point0,
+ Vector4 point1,
+ Vector4 point2) {
+
debugAssertM(
point0.w != 0 ||
point1.w != 0 ||
diff --git a/dep/g3dlite/source/Quat.cpp b/dep/g3dlite/source/Quat.cpp
index e06483b44cd..25c1711a94b 100644
--- a/dep/g3dlite/source/Quat.cpp
+++ b/dep/g3dlite/source/Quat.cpp
@@ -1,12 +1,12 @@
/**
- @file Quat.cpp
+ \file G3D/Quat.cpp
Quaternion implementation based on Watt & Watt page 363
- @author Morgan McGuire, graphics3d.com
+ \uthor Morgan McGuire, graphics3d.com
- @created 2002-01-23
- @edited 2010-03-31
+ \created 2002-01-23
+ \edited 2010-05-31
*/
#include "G3D/Quat.h"
@@ -45,50 +45,57 @@ Quat::Quat(const class Any& a) {
}
+Any Quat::toAny() const {
+ Any a(Any::ARRAY, "Quat");
+ a.append(x, y, z, w);
+ return a;
+}
+
+
Quat::Quat(const Matrix3& rot) {
static const int plus1mod3[] = {1, 2, 0};
// Find the index of the largest diagonal component
- // These ? operations hopefully compile to conditional
- // move instructions instead of branches.
+ // These ? operations hopefully compile to conditional
+ // move instructions instead of branches.
int i = (rot[1][1] > rot[0][0]) ? 1 : 0;
i = (rot[2][2] > rot[i][i]) ? 2 : i;
- // Find the indices of the other elements
+ // Find the indices of the other elements
int j = plus1mod3[i];
int k = plus1mod3[j];
- // Index the elements of the vector part of the quaternion as a float*
+ // Index the elements of the vector part of the quaternion as a float*
float* v = (float*)(this);
- // If we attempted to pre-normalize and trusted the matrix to be
- // perfectly orthonormal, the result would be:
- //
+ // If we attempted to pre-normalize and trusted the matrix to be
+ // perfectly orthonormal, the result would be:
+ //
// double c = sqrt((rot[i][i] - (rot[j][j] + rot[k][k])) + 1.0)
// v[i] = -c * 0.5
// v[j] = -(rot[i][j] + rot[j][i]) * 0.5 / c
// v[k] = -(rot[i][k] + rot[k][i]) * 0.5 / c
// w = (rot[j][k] - rot[k][j]) * 0.5 / c
- //
- // Since we're going to pay the sqrt anyway, we perform a post normalization, which also
- // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
+ //
+ // Since we're going to pay the sqrt anyway, we perform a post normalization, which also
+ // fixes any poorly normalized input. Multiply all elements by 2*c in the above, giving:
- // nc2 = -c^2
+ // nc2 = -c^2
double nc2 = ((rot[j][j] + rot[k][k]) - rot[i][i]) - 1.0;
- v[i] = nc2;
+ v[i] = (float)nc2;
w = (rot[j][k] - rot[k][j]);
v[j] = -(rot[i][j] + rot[j][i]);
v[k] = -(rot[i][k] + rot[k][i]);
- // We now have the correct result with the wrong magnitude, so normalize it:
+ // We now have the correct result with the wrong magnitude, so normalize it:
float s = sqrt(x*x + y*y + z*z + w*w);
if (s > 0.00001f) {
- s = 1.0f / s;
- x *= s;
- y *= s;
- z *= s;
- w *= s;
+ s = 1.0f / s;
+ x *= s;
+ y *= s;
+ z *= s;
+ w *= s;
} else {
// The quaternion is nearly zero. Make it 0 0 0 1
x = 0.0f;
@@ -116,25 +123,25 @@ void Quat::toAxisAngleRotation(
// Reduce the range of the angle.
- if (angle < 0) {
- angle = -angle;
- axis = -axis;
+ if (angle < 0) {
+ angle = -angle;
+ axis = -axis;
}
- while (angle > twoPi()) {
+ while (angle > twoPi()) {
angle -= twoPi();
}
- if (abs(angle) > pi()) {
- angle -= twoPi();
+ if (abs(angle) > pi()) {
+ angle -= twoPi();
}
// Make the angle positive.
- if (angle < 0.0f) {
- angle = -angle;
+ if (angle < 0.0f) {
+ angle = -angle;
axis = -axis;
- }
+ }
}
@@ -153,58 +160,71 @@ void Quat::toRotationMatrix(
rot = Matrix3(*this);
}
-
-Quat Quat::slerp(
- const Quat& _quat1,
+
+Quat Quat::slerp
+ (const Quat& _quat1,
float alpha,
- float threshold) const {
+ float threshold,
+ float maxAngle) const {
// From: Game Physics -- David Eberly pg 538-540
// Modified to include lerp for small angles, which
- // is a common practice.
+ // is a common practice.
- // See also:
- // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
+ // See also:
+ // http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/index.html
const Quat& quat0 = *this;
Quat quat1 = _quat1;
// angle between quaternion rotations
- float phi;
- float cosphi = quat0.dot(quat1);
+ float halfPhi;
+ float cosHalfPhi = quat0.dot(quat1);
- if (cosphi < 0) {
+ if (cosHalfPhi < 0) {
// Change the sign and fix the dot product; we need to
// loop the other way to get the shortest path
quat1 = -quat1;
- cosphi = -cosphi;
+ cosHalfPhi = -cosHalfPhi;
}
// Using G3D::aCos will clamp the angle to 0 and pi
- phi = static_cast<float>(G3D::aCos(cosphi));
+ halfPhi = static_cast<float>(G3D::aCos(cosHalfPhi));
- if (phi >= threshold) {
+ debugAssertM(halfPhi >= 0.0f, "Assumed acos returned a value >= 0");
+ if (halfPhi * 2.0f * alpha > maxAngle) {
+ // Back off alpha
+ alpha = maxAngle * 0.5f / halfPhi;
+ }
+
+ if (halfPhi >= threshold) {
// For large angles, slerp
float scale0, scale1;
- scale0 = sin((1.0f - alpha) * phi);
- scale1 = sin(alpha * phi);
+ scale0 = sin((1.0f - alpha) * halfPhi);
+ scale1 = sin(alpha * halfPhi);
- return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(phi);
+ return ( (quat0 * scale0) + (quat1 * scale1) ) / sin(halfPhi);
} else {
// For small angles, linear interpolate
- return quat0.nlerp(quat1, alpha);
+ return quat0.nlerp(quat1, alpha);
}
}
-Quat Quat::nlerp(
- const Quat& quat1,
+float Quat::angleBetween(const Quat& other) const {
+ const float d = this->dot(other);
+ return 2.0f * acos(fabsf(d));
+}
+
+
+Quat Quat::nlerp
+ (const Quat& quat1,
float alpha) const {
Quat result = (*this) * (1.0f - alpha) + quat1 * alpha;
- return result / result.magnitude();
+ return result / result.magnitude();
}
diff --git a/dep/g3dlite/source/Random.cpp b/dep/g3dlite/source/Random.cpp
index 2dda744a1ac..cbfa07dec0b 100644
--- a/dep/g3dlite/source/Random.cpp
+++ b/dep/g3dlite/source/Random.cpp
@@ -1,12 +1,12 @@
/**
- @file Random.cpp
+ \file Random.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2009-01-02
- @edited 2009-03-29
+ \created 2009-01-02
+ \edited 2012-03-29
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
#include "G3D/Random.h"
@@ -18,15 +18,23 @@ Random& Random::common() {
return r;
}
+
Random::Random(void* x) : state(NULL), m_threadsafe(false) {
(void)x;
}
Random::Random(uint32 seed, bool threadsafe) : m_threadsafe(threadsafe) {
+ state = new uint32[N];
+ reset(seed, threadsafe);
+}
+
+
+void Random::reset(uint32 seed, bool threadsafe) {
+ m_threadsafe = threadsafe;
+
const uint32 X = 1812433253UL;
- state = new uint32[N];
state[0] = seed;
for (index = 1; index < (int)N; ++index) {
state[index] = X * (state[index - 1] ^ (state[index - 1] >> 30)) + index;
@@ -115,6 +123,7 @@ void Random::generate() {
int Random::integer(int low, int high) {
+ debugAssert(high >= low);
int r = iFloor(low + (high - low + 1) * (double)bits() / 0xFFFFFFFFUL);
// There is a *very small* chance of generating
@@ -147,6 +156,15 @@ float Random::gaussian(float mean, float stdev) {
}
+void Random::cosSphere(float& x, float& y, float& z) {
+ cosHemi(x, y, z);
+ if (bits() & 1) {
+ // Choose the axis direction uniformly at random
+ z = -z;
+ }
+}
+
+
void Random::cosHemi(float& x, float& y, float& z) {
const float e1 = uniform();
const float e2 = uniform();
diff --git a/dep/g3dlite/source/Ray.cpp b/dep/g3dlite/source/Ray.cpp
index 0436ef0b323..8a8cf77c5b7 100644
--- a/dep/g3dlite/source/Ray.cpp
+++ b/dep/g3dlite/source/Ray.cpp
@@ -16,127 +16,128 @@
namespace G3D {
void Ray::set(const Vector3& origin, const Vector3& direction) {
- m_origin = origin;
- m_direction = direction;
- debugAssert(direction.isUnit());
-
- m_invDirection = Vector3::one() / direction;
-
- // ray slope
- ibyj = m_direction.x * m_invDirection.y;
- jbyi = m_direction.y * m_invDirection.x;
- jbyk = m_direction.y * m_invDirection.z;
- kbyj = m_direction.z * m_invDirection.y;
- ibyk = m_direction.x * m_invDirection.z;
- kbyi = m_direction.z * m_invDirection.x;
-
- // precomputed terms
- c_xy = m_origin.y - jbyi * m_origin.x;
- c_xz = m_origin.z - kbyi * m_origin.x;
- c_yx = m_origin.x - ibyj * m_origin.y;
- c_yz = m_origin.z - kbyj * m_origin.y;
- c_zx = m_origin.x - ibyk * m_origin.z;
- c_zy = m_origin.y - jbyk * m_origin.z;
-
- //ray slope classification
- if (m_direction.x < 0) {
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- classification = MMM;
- } else if (m_direction.z > 0) {
- classification = MMP;
- } else { //(m_direction.z >= 0)
- classification = MMO;
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if (m_direction.y == 0) {
- classification = MOM;
- } else {
- classification = MPM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = MOO;
- } else if (m_direction.z == 0) {
- classification = MPO;
- } else if (m_direction.y == 0) {
- classification = MOP;
- } else {
- classification = MPP;
- }
- }
- }
- } else { //(m_direction.x >= 0)
- if (m_direction.y < 0) {
- if (m_direction.z < 0) {
- if (m_direction.x == 0) {
- classification = OMM;
- } else {
- classification = PMM;
- }
- } else { //(m_direction.z >= 0)
- if ((m_direction.x == 0) && (m_direction.z == 0)) {
- classification = OMO;
- } else if (m_direction.z == 0) {
- classification = PMO;
- } else if (m_direction.x == 0) {
- classification = OMP;
- } else {
- classification = PMP;
- }
- }
- } else { //(m_direction.y >= 0)
- if (m_direction.z < 0) {
- if ((m_direction.x == 0) && (m_direction.y == 0)) {
- classification = OOM;
- } else if (m_direction.x == 0) {
- classification = OPM;
- } else if (m_direction.y == 0) {
- classification = POM;
- } else {
- classification = PPM;
- }
- } else { //(m_direction.z > 0)
- if (m_direction.x == 0) {
- if (m_direction.y == 0) {
- classification = OOP;
- } else if (m_direction.z == 0) {
- classification = OPO;
- } else {
- classification = OPP;
- }
- } else {
- if ((m_direction.y == 0) && (m_direction.z == 0)) {
- classification = POO;
- } else if (m_direction.y == 0) {
- classification = POP;
- } else if (m_direction.z == 0) {
- classification = PPO;
- } else {
- classification = PPP;
- }
- }
- }
- }
- }
+ m_origin = origin;
+ m_direction = direction;
+ debugAssert(direction.isUnit());
+
+ m_invDirection = Vector3::one() / direction;
+
+ // ray slope
+ ibyj = m_direction.x * m_invDirection.y;
+ jbyi = m_direction.y * m_invDirection.x;
+ jbyk = m_direction.y * m_invDirection.z;
+ kbyj = m_direction.z * m_invDirection.y;
+ ibyk = m_direction.x * m_invDirection.z;
+ kbyi = m_direction.z * m_invDirection.x;
+
+ // precomputed terms
+ c_xy = m_origin.y - jbyi * m_origin.x;
+ c_xz = m_origin.z - kbyi * m_origin.x;
+ c_yx = m_origin.x - ibyj * m_origin.y;
+ c_yz = m_origin.z - kbyj * m_origin.y;
+ c_zx = m_origin.x - ibyk * m_origin.z;
+ c_zy = m_origin.y - jbyk * m_origin.z;
+
+ //ray slope classification
+ if (m_direction.x < 0) {
+ if (m_direction.y < 0) {
+ if (m_direction.z < 0) {
+ classification = MMM;
+ } else if (m_direction.z > 0) {
+ classification = MMP;
+ } else { //(m_direction.z >= 0)
+ classification = MMO;
+ }
+ } else { //(m_direction.y >= 0)
+ if (m_direction.z < 0) {
+ if (m_direction.y == 0) {
+ classification = MOM;
+ } else {
+ classification = MPM;
+ }
+ } else { //(m_direction.z >= 0)
+ if ((m_direction.y == 0) && (m_direction.z == 0)) {
+ classification = MOO;
+ } else if (m_direction.z == 0) {
+ classification = MPO;
+ } else if (m_direction.y == 0) {
+ classification = MOP;
+ } else {
+ classification = MPP;
+ }
+ }
+ }
+ } else { //(m_direction.x >= 0)
+ if (m_direction.y < 0) {
+ if (m_direction.z < 0) {
+ if (m_direction.x == 0) {
+ classification = OMM;
+ } else {
+ classification = PMM;
+ }
+ } else { //(m_direction.z >= 0)
+ if ((m_direction.x == 0) && (m_direction.z == 0)) {
+ classification = OMO;
+ } else if (m_direction.z == 0) {
+ classification = PMO;
+ } else if (m_direction.x == 0) {
+ classification = OMP;
+ } else {
+ classification = PMP;
+ }
+ }
+ } else { //(m_direction.y >= 0)
+ if (m_direction.z < 0) {
+ if ((m_direction.x == 0) && (m_direction.y == 0)) {
+ classification = OOM;
+ } else if (m_direction.x == 0) {
+ classification = OPM;
+ } else if (m_direction.y == 0) {
+ classification = POM;
+ } else {
+ classification = PPM;
+ }
+ } else { //(m_direction.z > 0)
+ if (m_direction.x == 0) {
+ if (m_direction.y == 0) {
+ classification = OOP;
+ } else if (m_direction.z == 0) {
+ classification = OPO;
+ } else {
+ classification = OPP;
+ }
+ } else {
+ if ((m_direction.y == 0) && (m_direction.z == 0)) {
+ classification = POO;
+ } else if (m_direction.y == 0) {
+ classification = POP;
+ } else if (m_direction.z == 0) {
+ classification = PPO;
+ } else {
+ classification = PPP;
+ }
+ }
+ }
+ }
+ }
}
+
Ray::Ray(class BinaryInput& b) {
- deserialize(b);
+ deserialize(b);
}
void Ray::serialize(class BinaryOutput& b) const {
- m_origin.serialize(b);
- m_direction.serialize(b);
+ m_origin.serialize(b);
+ m_direction.serialize(b);
}
void Ray::deserialize(class BinaryInput& b) {
- m_origin.deserialize(b);
- m_direction.deserialize(b);
- set(m_origin, m_direction);
+ m_origin.deserialize(b);
+ m_direction.deserialize(b);
+ set(m_origin, m_direction);
}
diff --git a/dep/g3dlite/source/Rect2D.cpp b/dep/g3dlite/source/Rect2D.cpp
index e4148315a58..3aea02f512e 100644
--- a/dep/g3dlite/source/Rect2D.cpp
+++ b/dep/g3dlite/source/Rect2D.cpp
@@ -4,9 +4,9 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2003-11-13
- @created 2009-11-16
+ @created 2011-06-16
- Copyright 2000-2009, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -14,28 +14,56 @@
#include "G3D/Rect2D.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
namespace G3D {
+const Rect2D& Rect2D::empty() {
+ static Rect2D r;
+ return r;
+}
+
+
+void Rect2D::serialize(class BinaryOutput& b) const {
+ min.serialize(b);
+ max.serialize(b);
+}
+
+
+void Rect2D::deserialize(class BinaryInput& b) {
+ min.deserialize(b);
+ max.deserialize(b);
+}
+
+
/** \param any Must either Rect2D::xywh(#, #, #, #) or Rect2D::xyxy(#, #, #, #)*/
Rect2D::Rect2D(const Any& any) {
- any.verifyName("Rect2D");
+ if (any.name() == "Rect2D::empty" || any.name() == "AABox2D::empty") {
+ *this = empty();
+ return;
+ }
+
+ any.verifyName("Rect2D::xyxy", "Rect2D::xywh");
any.verifyType(Any::ARRAY);
any.verifySize(4);
- if (toUpper(any.name()) == "RECT2D::XYWH") {
+ if (any.name() == "Rect2D::xywh") {
*this = Rect2D::xywh(any[0], any[1], any[2], any[3]);
} else {
- any.verifyName("Rect2D::xyxy");
*this = Rect2D::xyxy(any[0], any[1], any[2], any[3]);
}
}
/** Converts the Rect2D to an Any. */
-Rect2D::operator Any() const {
- Any any(Any::ARRAY, "Rect2D::xywh");
- any.append(x0(), y0(), width(), height());
- return any;
+Any Rect2D::toAny() const {
+ if (isEmpty()) {
+ return Any(Any::ARRAY, "Rect2D::empty");
+ } else {
+ Any any(Any::ARRAY, "Rect2D::xywh");
+ any.append(Any(x0()), Any(y0()), Any(width()), Any(height()));
+ return any;
+ }
}
}
diff --git a/dep/g3dlite/source/ReferenceCount.cpp b/dep/g3dlite/source/ReferenceCount.cpp
deleted file mode 100644
index 2e1f117e0d9..00000000000
--- a/dep/g3dlite/source/ReferenceCount.cpp
+++ /dev/null
@@ -1,61 +0,0 @@
-/**
- @file ReferenceCount.cpp
-
- Reference Counting Garbage Collector for C++
-
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Adapted and extended from Justin Miller's "RGC" class that appeared in BYTE magazine.
- @cite See also http://www.jelovic.com/articles/cpp_without_memory_errors_slides.htm
-
- @created 2001-10-23
- @edited 2009-04-25
-*/
-#include "G3D/platform.h"
-#include "G3D/ReferenceCount.h"
-
-namespace G3D {
-
-ReferenceCountedObject::ReferenceCountedObject() :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
-
- debugAssertM(isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-void ReferenceCountedObject::ReferenceCountedObject_zeroWeakPointers() {
- // Tell all of my weak pointers that I'm gone.
-
- _WeakPtrLinkedList* node = ReferenceCountedObject_weakPointer;
-
- while (node != NULL) {
- // Notify the weak pointer that it is going away
- node->weakPtr->objectCollected();
-
- // Free the node and advance
- _WeakPtrLinkedList* tmp = node;
- node = node->next;
- delete tmp;
- }
-}
-
-ReferenceCountedObject::~ReferenceCountedObject() {}
-
-
-ReferenceCountedObject::ReferenceCountedObject(const ReferenceCountedObject& notUsed) :
- ReferenceCountedObject_refCount(0),
- ReferenceCountedObject_weakPointer(0) {
- (void)notUsed;
- debugAssertM(G3D::isValidHeapPointer(this),
- "Reference counted objects must be allocated on the heap.");
-}
-
-ReferenceCountedObject& ReferenceCountedObject::operator=(const ReferenceCountedObject& other) {
- (void)other;
- // Nothing changes when I am assigned; the reference count on
- // both objects is the same (although my super-class probably
- // changes).
- return *this;
-}
-
-} // G3D
diff --git a/dep/g3dlite/source/RegistryUtil.cpp b/dep/g3dlite/source/RegistryUtil.cpp
index 7c9e56f79ae..72c31212049 100644
--- a/dep/g3dlite/source/RegistryUtil.cpp
+++ b/dep/g3dlite/source/RegistryUtil.cpp
@@ -11,7 +11,7 @@
#include "G3D/platform.h"
// This file is only used on Windows
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include "G3D/RegistryUtil.h"
#include "G3D/System.h"
@@ -24,7 +24,6 @@
# define HKEY_PERFORMANCE_NLSTEXT ((HKEY)((LONG)0x80000060))
# endif
#endif
-
namespace G3D {
// static helpers
@@ -256,7 +255,8 @@ bool RegistryUtil::writeString(const std::string& key, const std::string& value,
debugAssert(result == ERROR_SUCCESS || result == ERROR_FILE_NOT_FOUND);
if (result == ERROR_SUCCESS) {
- result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(data.c_str()), (data.size() + 1));
+ alwaysAssertM(data.size() < 0xFFFFFFFE, "String too long");
+ result = RegSetValueExA(openKey, value.c_str(), 0, REG_SZ, reinterpret_cast<const BYTE*>(data.c_str()), (int)(data.size() + 1));
debugAssertM(result == ERROR_SUCCESS, "Could not write registry key value.");
RegCloseKey(openKey);
@@ -296,4 +296,4 @@ static HKEY getRootKeyFromString(const char* str, size_t length) {
} // namespace G3D
-#endif // G3D_WIN32
+#endif // G3D_WINDOWS
diff --git a/dep/g3dlite/source/Sphere.cpp b/dep/g3dlite/source/Sphere.cpp
index 4ed0811cb29..5c2eb91cd2a 100644
--- a/dep/g3dlite/source/Sphere.cpp
+++ b/dep/g3dlite/source/Sphere.cpp
@@ -1,12 +1,12 @@
/**
- @file Sphere.cpp
+ \file G3D.lib/source/Sphere.cpp
Sphere class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2001-04-17
- @edited 2009-01-20
+ \created 2001-04-17
+ \edited 2011-02-10
*/
#include "G3D/platform.h"
@@ -16,11 +16,37 @@
#include "G3D/BinaryInput.h"
#include "G3D/AABox.h"
#include "G3D/Plane.h"
+#include "G3D/Any.h"
namespace G3D {
int32 Sphere::dummy;
+Sphere::Sphere(const Any& a) : radius(0) {
+ a.verifyName("Sphere");
+ a.verifyType(Any::ARRAY);
+ if (a.size() == 1) {
+ radius = a[0];
+ } else if (a.size() == 2) {
+ center = a[0];
+ radius = a[1];
+ } else {
+ a.verify(false, "Sphere must recieve exactly 1 or two arguments.");
+ }
+}
+
+
+Any Sphere::toAny() const {
+ Any a(Any::ARRAY, "Sphere");
+ if (center != Point3::zero()) {
+ a.append(center);
+ }
+
+ a.append(radius);
+ return a;
+}
+
+
Sphere::Sphere(class BinaryInput& b) {
deserialize(b);
}
@@ -38,6 +64,12 @@ void Sphere::deserialize(class BinaryInput& b) {
}
+const Sphere& Sphere::inf() {
+ static const Sphere s(Point3::zero(), finf());
+ return s;
+}
+
+
std::string Sphere::toString() const {
return format("Sphere(<%g, %g, %g>, %g)",
center.x, center.y, center.z, radius);
@@ -82,19 +114,19 @@ void Sphere::merge(const Sphere& other) {
bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask,
- uint32& outMask) const {
+ const Array<Plane>& plane,
+ int& cullingPlaneIndex,
+ const uint32 inMask,
+ uint32& outMask) const {
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask, outMask);
}
bool Sphere::culledBy(
- const Array<Plane>& plane,
- int& cullingPlaneIndex,
- const uint32 inMask) const {
+ const Array<Plane>& plane,
+ int& cullingPlaneIndex,
+ const uint32 inMask) const {
return culledBy(plane.getCArray(), plane.size(), cullingPlaneIndex, inMask);
}
@@ -103,8 +135,8 @@ bool Sphere::culledBy(
bool Sphere::culledBy(
const class Plane* plane,
int numPlanes,
- int& cullingPlane,
- const uint32 _inMask,
+ int& cullingPlane,
+ const uint32 _inMask,
uint32& childMask) const {
if (radius == finf()) {
@@ -112,45 +144,45 @@ bool Sphere::culledBy(
return false;
}
- uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ uint32 inMask = _inMask;
+ assert(numPlanes < 31);
childMask = 0;
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
+ // vertices are in the negative half space.
+ for (int p = 0; p < numPlanes; ++p) {
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
-
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+
bool culledLow = ! plane[p].halfSpaceContainsFinite(center + plane[p].normal() * radius);
bool culledHigh = ! plane[p].halfSpaceContainsFinite(center - plane[p].normal() * radius);
- if (culledLow) {
- // Plane p culled the sphere
- cullingPlane = p;
+ if (culledLow) {
+ // Plane p culled the sphere
+ cullingPlane = p;
// The caller should not recurse into the children,
// since the parent is culled. If they do recurse,
// make them only test against this one plane, which
// will immediately cull the volume.
childMask = 1 << p;
- return true;
+ return true;
} else if (culledHigh) {
// The bounding volume straddled the plane; we have
// to keep testing against this plane
childMask |= (1 << p);
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
@@ -158,32 +190,34 @@ bool Sphere::culledBy(
bool Sphere::culledBy(
const class Plane* plane,
int numPlanes,
- int& cullingPlane,
- const uint32 _inMask) const {
+ int& cullingPlane,
+ const uint32 _inMask) const {
+ // Don't cull if the sphere has infinite radius
+ if(!isFinite(radius)) return false;
- uint32 inMask = _inMask;
- assert(numPlanes < 31);
+ uint32 inMask = _inMask;
+ assert(numPlanes < 31);
// See if there is one plane for which all of the
- // vertices are in the negative half space.
- for (int p = 0; p < numPlanes; p++) {
-
- // Only test planes that are not masked
- if ((inMask & 1) != 0) {
- bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
- if (culled) {
- // Plane p culled the sphere
- cullingPlane = p;
- return true;
+ // vertices are in the negative half space.
+ for (int p = 0; p < numPlanes; ++p) {
+
+ // Only test planes that are not masked
+ if ((inMask & 1) != 0) {
+ bool culled = ! plane[p].halfSpaceContains(center + plane[p].normal() * radius);
+ if (culled) {
+ // Plane p culled the sphere
+ cullingPlane = p;
+ return true;
}
- }
+ }
// Move on to the next bit.
- inMask = inMask >> 1;
+ inMask = inMask >> 1;
}
// None of the planes could cull this box
- cullingPlane = -1;
+ cullingPlane = -1;
return false;
}
diff --git a/dep/g3dlite/source/SplineBase.cpp b/dep/g3dlite/source/SplineBase.cpp
index 41221624b06..5904e9a1aa2 100644
--- a/dep/g3dlite/source/SplineBase.cpp
+++ b/dep/g3dlite/source/SplineBase.cpp
@@ -4,7 +4,7 @@
namespace G3D {
float SplineBase::getFinalInterval() const {
- if (! cyclic) {
+ if (extrapolationMode != SplineExtrapolationMode::CYCLIC) {
return 0;
} else if (finalInterval <= 0) {
int N = time.size();
@@ -97,7 +97,7 @@ void SplineBase::computeIndex(float s, int& i, float& u) const {
// No control points to work with
i = 0;
u = 0.0;
- } else if (cyclic) {
+ } else if (extrapolationMode == SplineExtrapolationMode::CYCLIC) {
float fi = getFinalInterval();
// Cyclic spline
@@ -156,7 +156,7 @@ void SplineBase::computeIndex(float s, int& i, float& u) const {
computeIndexInBounds(s, i, u);
} // if in bounds
- } // if cyclic
+ } // extrapolation Mode
}
}
diff --git a/dep/g3dlite/source/Stopwatch.cpp b/dep/g3dlite/source/Stopwatch.cpp
index 9b785d50295..713835ea7ab 100644
--- a/dep/g3dlite/source/Stopwatch.cpp
+++ b/dep/g3dlite/source/Stopwatch.cpp
@@ -105,15 +105,16 @@ void Stopwatch::reset() {
void Stopwatch::after(const std::string& s) {
RealTime now = System::time();
- debugPrintf("%s: %10s - %8fs since %s (%fs since start)\n",
- myName.c_str(),
- s.c_str(),
- now - prevTime,
- prevMark.c_str(),
- now - startTime);
+ if (m_enabled) {
+ debugPrintf("%s: %10s - %8fs since %s (%fs since start)\n",
+ myName.c_str(),
+ s.c_str(),
+ now - prevTime,
+ prevMark.c_str(),
+ now - startTime);
+ }
prevTime = now;
prevMark = s;
}
}
-
diff --git a/dep/g3dlite/source/System.cpp b/dep/g3dlite/source/System.cpp
index 281104d39f1..b2f8cb886da 100644
--- a/dep/g3dlite/source/System.cpp
+++ b/dep/g3dlite/source/System.cpp
@@ -1,7 +1,7 @@
/**
- @file System.cpp
+ \file System.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
Note: every routine must call init() first.
@@ -10,8 +10,8 @@
can be used at all. At runtime, processor detection is used to
determine if we can safely call the routines that use that assembly.
- @created 2003-01-25
- @edited 2010-01-03
+ \created 2003-01-25
+ \edited 2012-01-05
*/
#include "G3D/platform.h"
@@ -37,17 +37,14 @@
// allocation and use the operating system's malloc.
//#define NO_BUFFERPOOL
-#if defined(__i386__) || defined(__x86_64__) || defined(G3D_WIN32)
-# define G3D_NOT_OSX_PPC
-#endif
-
#include <cstdlib>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
# include <conio.h>
# include <sys/timeb.h>
# include "G3D/RegistryUtil.h"
+#include <Ole2.h>
#elif defined(G3D_LINUX)
@@ -81,13 +78,11 @@
#endif
// SIMM include
-#ifdef __SSE__
#include <xmmintrin.h>
-#endif
-
-namespace G3D {
+namespace G3D {
+
/** Checks if the CPUID command is available on the processor (called from init) */
static bool checkForCPUID();
@@ -173,10 +168,6 @@ void System::init() {
m_cpuArch = "AMD Processor";
break;
- case 0x69727943: // CyrixInstead
- m_cpuArch = "Cyrix Processor";
- break;
-
default:
m_cpuArch = "Unknown Processor Vendor";
break;
@@ -195,43 +186,40 @@ void System::init() {
// Get the operating system name (also happens to read some other information)
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
+ HRESULT r = OleInitialize(NULL);
// Note that this overrides some of the values computed above
bool success = RegistryUtil::readInt32
("HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0",
"~MHz", m_cpuSpeed);
-
+ HRESULT s = OleInitialize(NULL);
SYSTEM_INFO systemInfo;
GetSystemInfo(&systemInfo);
const char* arch = NULL;
switch (systemInfo.wProcessorArchitecture) {
case PROCESSOR_ARCHITECTURE_INTEL:
- arch = "Intel";
+ arch = "x86 Intel";
break;
- case PROCESSOR_ARCHITECTURE_MIPS:
- arch = "MIPS";
- break;
+ case PROCESSOR_ARCHITECTURE_AMD64:
+ arch = "x64 Intel/AMD";
+ break;
- case PROCESSOR_ARCHITECTURE_ALPHA:
- arch = "Alpha";
- break;
-
- case PROCESSOR_ARCHITECTURE_PPC:
- arch = "Power PC";
- break;
+ case PROCESSOR_ARCHITECTURE_ARM:
+ arch = "ARM";
+ break;
default:
arch = "Unknown";
+ break;
}
m_numCores = systemInfo.dwNumberOfProcessors;
- uint32 maxAddr = (uint32)systemInfo.lpMaximumApplicationAddress;
+ uint64_t maxAddr = reinterpret_cast<uint64_t>(systemInfo.lpMaximumApplicationAddress);
{
char c[1024];
- sprintf(c, "%d x %d-bit %s processor",
+ sprintf(c, "%d - %s cores",
systemInfo.dwNumberOfProcessors,
- (int)(::log((double)maxAddr) / ::log(2.0) + 2.0),
arch);
m_cpuArch = c;
}
@@ -261,12 +249,13 @@ void System::init() {
int len = 100;
char* r = (char*)::malloc(len * sizeof(char));
- fgets(r, len, f);
+ (void)fgets(r, len, f);
// Remove trailing newline
if (r[strlen(r) - 1] == '\n') {
r[strlen(r) - 1] = '\0';
}
fclose(f);
+ f = NULL;
m_operatingSystem = r;
::free(r);
@@ -294,72 +283,103 @@ void System::init() {
m_secondsPerNS = 1.0 / 1.0e9;
// System Architecture:
- const NXArchInfo* pInfo = NXGetLocalArchInfo();
-
- if (pInfo) {
- m_cpuArch = pInfo->description;
-
- switch (pInfo->cputype) {
- case CPU_TYPE_POWERPC:
- switch(pInfo->cpusubtype){
- case CPU_SUBTYPE_POWERPC_750:
- case CPU_SUBTYPE_POWERPC_7400:
- case CPU_SUBTYPE_POWERPC_7450:
- m_cpuVendor = "Motorola";
- break;
- case CPU_SUBTYPE_POWERPC_970:
- m_cpuVendor = "IBM";
- break;
- }
- break;
-
+ const NXArchInfo* pInfo = NXGetLocalArchInfo();
+
+ if (pInfo) {
+ m_cpuArch = pInfo->description;
+
+ switch (pInfo->cputype) {
+ case CPU_TYPE_POWERPC:
+ switch(pInfo->cpusubtype){
+ case CPU_SUBTYPE_POWERPC_750:
+ case CPU_SUBTYPE_POWERPC_7400:
+ case CPU_SUBTYPE_POWERPC_7450:
+ m_cpuVendor = "Motorola";
+ break;
+ case CPU_SUBTYPE_POWERPC_970:
+ m_cpuVendor = "IBM";
+ break;
+ }
+ break;
+
case CPU_TYPE_I386:
m_cpuVendor = "Intel";
break;
- }
- }
+ }
+ }
# endif
initTime();
getStandardProcessorExtensions();
+
+ m_appDataDir = FilePath::parent(System::currentProgramFilename());
}
void getG3DVersion(std::string& s) {
+
+ const char* build =
+# ifdef G3D_64BIT
+ "64-bit";
+# else
+ "32-bit";
+# endif
+
+ const char* debug =
+# ifdef G3D_DEBUG
+ " (Debug)";
+# else
+ "";
+# endif
+
char cstr[100];
if ((G3D_VER % 100) != 0) {
- sprintf(cstr, "G3D %d.%02d beta %d",
+ sprintf(cstr, "G3D Innovation Engine %d.%02d beta %d, %s%s",
G3D_VER / 10000,
(G3D_VER / 100) % 100,
- G3D_VER % 100);
+ G3D_VER % 100,
+ build,
+ debug);
} else {
- sprintf(cstr, "G3D %d.%02d",
+ sprintf(cstr, "G3D Innovation Engine %d.%02d, %s%s",
G3D_VER / 10000,
- (G3D_VER / 100) % 100);
+ (G3D_VER / 100) % 100,
+ build,
+ debug);
}
+
s = cstr;
}
+// Places where specific files were most recently found. This is
+// used to cache seeking of common files.
+static Table<std::string, std::string> lastFound;
+
+// Places to look in findDataFile
+static Array<std::string> directoryArray;
+#define MARK_LOG()
+//#define MARK_LOG() logPrintf("%s(%d)\n", __FILE__, __LINE__)
std::string System::findDataFile
-(const std::string& full,
- bool errorIfNotFound) {
+(const std::string& _full,
+ bool errorIfNotFound,
+ bool caseSensitive) {
+MARK_LOG();
- // Places where specific files were most recently found. This is
- // used to cache seeking of common files.
- static Table<std::string, std::string> lastFound;
+ const std::string full = FilePath::expandEnvironmentVariables(_full);
// First check if the file exists as requested. This will go
// through the FileSystemCache, so most calls do not touch disk.
- if (FileSystem::exists(full)) {
+ if (FileSystem::exists(full, true, caseSensitive)) {
return full;
}
+MARK_LOG();
// Now check where we previously found this file.
std::string* last = lastFound.getPointer(full);
if (last != NULL) {
- if (FileSystem::exists(*last)) {
+ if (FileSystem::exists(*last, true, caseSensitive)) {
// Even if cwd has changed the file is still present.
// We won't notice if it has been deleted, however.
return *last;
@@ -369,11 +389,10 @@ std::string System::findDataFile
}
}
- // Places to look
- static Array<std::string> directoryArray;
+MARK_LOG();
- std::string initialAppDataDir(instance().m_appDataDir);
- const char* g3dPath = getenv("G3DDATA");
+ const std::string initialAppDataDir(instance().m_appDataDir);
+ const char* g3dPath = getenv("G3D9DATA");
if (directoryArray.size() == 0) {
// Initialize the directory array
@@ -381,18 +400,27 @@ std::string System::findDataFile
Array<std::string> baseDirArray;
- baseDirArray.append("");
+ baseDirArray.append(FileSystem::currentDirectory());
+MARK_LOG();
if (! initialAppDataDir.empty()) {
+MARK_LOG();
baseDirArray.append(initialAppDataDir);
+ baseDirArray.append(pathConcat(initialAppDataDir, "data"));
+ baseDirArray.append(pathConcat(initialAppDataDir, "data.zip"));
+ } else {
+MARK_LOG();
+ baseDirArray.append("data");
+ baseDirArray.append("data.zip");
}
+MARK_LOG();
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
if (g3dPath == NULL) {
// If running the demos under visual studio from the G3D.sln file,
// this will locate the data directory.
const char* paths[] = {"../data-files/", "../../data-files/", "../../../data-files/", NULL};
for (int i = 0; paths[i]; ++i) {
- if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"))) {
+ if (FileSystem::exists(pathConcat(paths[i], "G3D-DATA-README.TXT"), true, caseSensitive)) {
g3dPath = paths[i];
break;
}
@@ -405,96 +433,91 @@ std::string System::findDataFile
}
static const std::string subdirs[] =
- {"font", "gui", "SuperShader", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", ""};
+ {"font", "gui", "shader", "model", "cubemap", "icon", "material", "image", "md2", "md3", "ifs", "3ds", "sky", "music", "sound", "scene", ""};
for (int j = 0; j < baseDirArray.size(); ++j) {
std::string d = baseDirArray[j];
+//logPrintf("%s", d.c_str());
if ((d == "") || FileSystem::exists(d)) {
+//logPrintf(" exists\n");
directoryArray.append(d);
for (int i = 0; ! subdirs[i].empty(); ++i) {
const std::string& p = pathConcat(d, subdirs[i]);
- if (FileSystem::exists(p)) {
+ if (FileSystem::exists(p, true, caseSensitive)) {
directoryArray.append(p);
}
}
+ } else {
+//logPrintf(" does not exist\n");
}
}
logLazyPrintf("Initializing System::findDataFile took %fs\n", System::time() - t0);
+
}
+MARK_LOG();
for (int i = 0; i < directoryArray.size(); ++i) {
const std::string& p = pathConcat(directoryArray[i], full);
- if (FileSystem::exists(p)) {
+ if (FileSystem::exists(p, true, caseSensitive)) {
lastFound.set(full, p);
return p;
}
}
+MARK_LOG();
if (errorIfNotFound) {
- // Generate an error message
+ // Generate an error message. Delay this operation until we know that we need it;
+ // otherwise all of the string concatenation would run on each successful find.
std::string locations;
for (int i = 0; i < directoryArray.size(); ++i) {
locations += "\'" + pathConcat(directoryArray[i], full) + "'\n";
}
+MARK_LOG();
std::string msg = "Could not find '" + full + "'.\n\n";
- msg += "cwd = \'" + FileSystem::currentDirectory() + "\'\n";
+ msg += " cwd = '" + FileSystem::currentDirectory() + "'\n";
if (g3dPath) {
- msg += "G3DDATA = ";
- if (! FileSystem::exists(g3dPath)) {
- msg += "(illegal path!) ";
+ msg += " G3D9DATA = '" + std::string(g3dPath) + "'";
+ if (! FileSystem::exists(g3dPath, true, caseSensitive)) {
+ msg += " (illegal path!)";
}
- msg += std::string(g3dPath) + "\'\n";
+ msg += "\n";
} else {
- msg += "(G3DDATA environment variable is undefined)\n";
+ msg += " G3D9DATA = (environment variable is not defined)\n";
}
- msg += "GApp::Settings.dataDir = ";
- if (! FileSystem::exists(initialAppDataDir)) {
- msg += "(illegal path!) ";
+MARK_LOG();
+ msg += " GApp::Settings.dataDir = '" + initialAppDataDir + "'";
+ if (! FileSystem::exists(initialAppDataDir, true, caseSensitive)) {
+ msg += " (illegal path!)";
}
- msg += std::string(initialAppDataDir) + "\'\n";
+ msg += "\n";
- msg += "\nLocations searched:\n" + locations;
+ msg += "\nFilenames tested:\n" + locations;
+MARK_LOG();
+logPrintf("%s\n", msg.c_str());
+ throw FileNotFound(full, msg);
alwaysAssertM(false, msg);
}
+MARK_LOG();
// Not found
return "";
}
-
+#undef MARK_LOG
void System::setAppDataDir(const std::string& path) {
instance().m_appDataDir = path;
+
+ // Wipe the findDataFile cache
+ lastFound.clear();
+ directoryArray.clear();
}
-std::string demoFindData(bool errorIfNotFound) {
- static const char* g3dPath = getenv("G3DDATA");
- if (g3dPath) {
- return g3dPath;
-# ifdef G3D_WIN32
- } else if (FileSystem::exists("../data")) {
- // G3D install on Windows
- return "../data";
- } else if (FileSystem::exists("../data-files")) {
- // G3D source on Windows
- return "../data-files";
- } else if (FileSystem::exists("c:/libraries/G3D/data")) {
- return "c:/libraries/G3D/data";
-# else
- } else if (FileSystem::exists("../../../../data")) {
- // G3D install on Unix
- return "../../../../data";
- } else if (FileSystem::exists("../../../../data-files")) {
- // G3D source on Unix
- return "../../../../data-files";
- } else if (FileSystem::exists("/usr/local/G3D/data")) {
- return "/usr/local/G3D/data";
-# endif
- } else {
- return "";
- }
+void System::cleanup() {
+ lastFound.clear();
+ directoryArray.clear();
}
@@ -564,12 +587,15 @@ void System::getStandardProcessorExtensions() {
#endif
}
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memcpy SIMD to all platforms")
-/** Michael Herf's fast memcpy */
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+// 32-bit
+/** Michael Herf's fast memcpy. Assumes 16-byte alignment */
void memcpyMMX(void* dst, const void* src, int nbytes) {
int remainingBytes = nbytes;
+ alwaysAssertM((int)dst % 16 == 0, format("Must be on 16-byte boundary. dst = 0x%x", dst));
+ alwaysAssertM((int)src % 16 == 0, format("Must be on 16-byte boundary. src = 0x%x", src));
+
if (nbytes > 64) {
_asm {
mov esi, src
@@ -615,8 +641,13 @@ void memcpyMMX(void* dst, const void* src, int nbytes) {
#endif
void System::memcpy(void* dst, const void* src, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- memcpyMMX(dst, src, numBytes);
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ // The overhead of our memcpy seems to only be worthwhile on large arrays
+ if (((size_t)dst % 16 == 0) && ((size_t)src % 16 == 0) && (numBytes > 3400000)) {
+ memcpyMMX(dst, src, numBytes);
+ } else {
+ ::memcpy(dst, src, numBytes);
+ }
#else
::memcpy(dst, src, numBytes);
#endif
@@ -625,9 +656,7 @@ void System::memcpy(void* dst, const void* src, size_t numBytes) {
/** Michael Herf's fastest memset. n32 must be filled with the same
character repeated. */
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- #pragma message("Port System::memfill SIMD to all platforms")
-
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
// On x86 processors, use MMX
void memfill(void *dst, int n32, unsigned long i) {
@@ -664,10 +693,15 @@ void memfill(void *dst, int n32, unsigned long i) {
void System::memset(void* dst, uint8 value, size_t numBytes) {
-#if defined(G3D_WIN32) && !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
- uint32 v = value;
- v = v + (v << 8) + (v << 16) + (v << 24);
- G3D::memfill(dst, v, numBytes);
+ alwaysAssertM(dst != NULL, "Cannot memset NULL address.");
+#if defined(G3D_WINDOWS) && defined(_M_IX86) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit Windows platforms or using MinGW */
+ if ((((size_t)dst % 16) == 0) && (numBytes >= 512*1024)) {
+ uint32 v = value;
+ v = v + (v << 8) + (v << 16) + (v << 24);
+ G3D::memfill(dst, v, numBytes);
+ } else {
+ ::memset(dst, value, numBytes);
+ }
#else
::memset(dst, value, numBytes);
#endif
@@ -683,7 +717,7 @@ static std::string computeAppName(const std::string& start) {
if (start[start.size() - 1] == 'd') {
// Maybe remove the 'd'; see if ../ or ../../ has the same name
char tmp[1024];
- getcwd(tmp, sizeof(tmp));
+ (void)getcwd(tmp, sizeof(tmp));
std::string drive, base, ext;
Array<std::string> path;
parseFilename(tmp, drive, path, base, ext);
@@ -712,7 +746,7 @@ std::string& System::appName() {
std::string System::currentProgramFilename() {
char filename[2048];
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
{
GetModuleFileNameA(NULL, filename, sizeof(filename));
}
@@ -730,6 +764,7 @@ std::string System::currentProgramFilename() {
int s = fread(filename, 1, sizeof(filename), fd);
// filename will contain a newline. Overwrite it:
filename[s - 1] = '\0';
+ pclose(fd);
}
# else
{
@@ -784,7 +819,7 @@ void System::sleep(RealTime t) {
}
if (sleepTime >= 0) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// Translate to milliseconds
Sleep((int)(sleepTime * 1e3));
#else
@@ -800,16 +835,16 @@ void System::sleep(RealTime t) {
void System::consoleClearScreen() {
-# ifdef G3D_WIN32
- system("cls");
+# ifdef G3D_WINDOWS
+ (void)system("cls");
# else
- system("clear");
+ (void)system("clear");
# endif
}
bool System::consoleKeyPressed() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
return _kbhit() != 0;
@@ -851,18 +886,18 @@ bool System::consoleKeyPressed() {
int System::consoleReadKey() {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
return _getch();
# else
char c;
- read(0, &c, 1);
+ (void)read(0, &c, 1);
return c;
# endif
}
void System::initTime() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if (QueryPerformanceFrequency(&m_counterFrequency)) {
QueryPerformanceCounter(&m_start);
}
@@ -888,11 +923,7 @@ void System::initTime() {
if (localTimeVals) {
// tm_gmtoff is already corrected for daylight savings.
- #ifdef __CYGWIN__
- local = local + _timezone;
- #else
local = local + localTimeVals->tm_gmtoff;
- #endif
}
m_realWorldGetTickTime0 = local;
@@ -901,7 +932,7 @@ void System::initTime() {
RealTime System::time() {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
@@ -924,12 +955,11 @@ RealTime System::time() {
////////////////////////////////////////////////////////////////
-
-#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof(uint32))
-#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof(uint32))
-#define USERSIZE_TO_REALSIZE(x) ((x) + sizeof(uint32))
-#define REALSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr) + sizeof(uint32))
-#define USERSIZE_FROM_USERPTR(u) (*(uint32*)USERPTR_TO_REALPTR(ptr))
+#define REALPTR_TO_USERPTR(x) ((uint8*)(x) + sizeof(size_t))
+#define USERPTR_TO_REALPTR(x) ((uint8*)(x) - sizeof(size_t))
+#define USERSIZE_TO_REALSIZE(x) ((x) + sizeof(size_t))
+#define REALSIZE_FROM_USERPTR(u) (*(size_t*)USERPTR_TO_REALPTR(ptr) + sizeof(size_t))
+#define USERSIZE_FROM_USERPTR(u) (*(size_t*)USERPTR_TO_REALPTR(ptr))
class BufferPool {
public:
@@ -942,15 +972,20 @@ public:
Tiny buffers are 128 bytes long because that seems to align well with
cache sizes on many machines.
*/
+#ifdef G3D_64BIT
+ // 64-bit machines have larger pointers...and probably have more memory as well
+ enum {tinyBufferSize = 256, smallBufferSize = 2048, medBufferSize = 8192};
+#else
enum {tinyBufferSize = 128, smallBufferSize = 1024, medBufferSize = 4096};
+#endif
/**
Most buffers we're allowed to store.
- 250000 * 128 = 32 MB (preallocated)
- 10000 * 1024 = 10 MB (allocated on demand)
- 1024 * 4096 = 4 MB (allocated on demand)
+ 250000 * { 128 | 256} = {32 | 64} MB (preallocated)
+ 40000 * {1024 | 2048} = {40 | 80} MB (allocated on demand)
+ 5000 * {4096 | 8192} = {20 | 40} MB (allocated on demand)
*/
- enum {maxTinyBuffers = 250000, maxSmallBuffers = 10000, maxMedBuffers = 1024};
+ enum {maxTinyBuffers = 250000, maxSmallBuffers = 40000, maxMedBuffers = 5000};
private:
@@ -995,31 +1030,6 @@ private:
m_lock.unlock();
}
-#if 0 //-----------------------------------------------old mutex
-# ifdef G3D_WIN32
- CRITICAL_SECTION mutex;
-# else
- pthread_mutex_t mutex;
-# endif
-
- /** Provide synchronization between threads */
- void lock() {
-# ifdef G3D_WIN32
- EnterCriticalSection(&mutex);
-# else
- pthread_mutex_lock(&mutex);
-# endif
- }
-
- void unlock() {
-# ifdef G3D_WIN32
- LeaveCriticalSection(&mutex);
-# else
- pthread_mutex_unlock(&mutex);
-# endif
- }
-#endif //-------------------------------------------old mutex
-
/**
Malloc out of the tiny heap. Returns NULL if allocation failed.
*/
@@ -1133,7 +1143,7 @@ public:
of a buffer.
Primarily useful for detecting leaks.*/
// TODO: make me an atomic int!
- volatile int bytesAllocated;
+ volatile size_t bytesAllocated;
BufferPool() {
totalMallocs = 0;
@@ -1142,7 +1152,7 @@ public:
mallocsFromSmallPool = 0;
mallocsFromMedPool = 0;
- bytesAllocated = true;
+ bytesAllocated = 0;
tinyPoolSize = 0;
tinyHeap = NULL;
@@ -1161,7 +1171,7 @@ public:
tinyPoolSize = maxTinyBuffers;
#if 0 ///---------------------------------- old mutex
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
InitializeCriticalSection(&mutex);
# else
pthread_mutex_init(&mutex, NULL);
@@ -1175,7 +1185,7 @@ public:
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
#if 0 //-------------------------------- old mutex
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
DeleteCriticalSection(&mutex);
# else
// No destruction on pthreads
@@ -1274,6 +1284,11 @@ public:
RealPtr ptr = ::malloc(USERSIZE_TO_REALSIZE(bytes));
if (ptr == NULL) {
+# ifdef G3D_WINDOWS
+ // Check for memory corruption
+ alwaysAssertM(_CrtCheckMemory() == TRUE, "Heap corruption detected.");
+# endif
+
// Flush memory pools to try and recover space
flushPool(smallPool, smallPoolSize);
flushPool(medPool, medPoolSize);
@@ -1303,7 +1318,7 @@ public:
return NULL;
}
- *(uint32*)ptr = bytes;
+ ((size_t*)ptr)[0] = bytes;
return REALPTR_TO_USERPTR(ptr);
}
@@ -1324,7 +1339,7 @@ public:
return;
}
- uint32 bytes = USERSIZE_FROM_USERPTR(ptr);
+ size_t bytes = USERSIZE_FROM_USERPTR(ptr);
lock();
if (bytes <= smallBufferSize) {
@@ -1466,14 +1481,17 @@ void System::free(void* p) {
void* System::alignedMalloc(size_t bytes, size_t alignment) {
- alwaysAssertM(isPow2(alignment), "alignment must be a power of 2");
+ alwaysAssertM(isPow2((uint32)alignment), "alignment must be a power of 2");
// We must align to at least a word boundary.
- alignment = iMax(alignment, sizeof(void *));
+ alignment = max(alignment, sizeof(void *));
- // Pad the allocation size with the alignment size and the
- // size of the redirect pointer.
- size_t totalBytes = bytes + alignment + sizeof(void*);
+ // Pad the allocation size with the alignment size and the size of
+ // the redirect pointer. This is the worst-case size we'll need.
+ // Since the alignment size is at least teh word size, we don't
+ // need to allocate space for the redirect pointer. We repeat the max here
+ // for clarity.
+ size_t totalBytes = bytes + max(alignment, sizeof(void*));
size_t truePtr = (size_t)System::malloc(totalBytes);
@@ -1483,25 +1501,31 @@ void* System::alignedMalloc(size_t bytes, size_t alignment) {
}
debugAssert(isValidHeapPointer((void*)truePtr));
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// The blocks we return will not be valid Win32 debug heap
// pointers because they are offset
// debugAssert(_CrtIsValidPointer((void*)truePtr, totalBytes, TRUE) );
#endif
- // The return pointer will be the next aligned location (we must at least
- // leave space for the redirect pointer, however).
- size_t alignedPtr = truePtr + sizeof(void*);
- // 2^n - 1 has the form 1111... in binary.
- uint32 bitMask = (alignment - 1);
+ // We want alignedPtr % alignment == 0, which we'll compute with a
+ // binary AND because 2^n - 1 has the form 1111... in binary.
+ const size_t bitMask = (alignment - 1);
- // Advance forward until we reach an aligned location.
- while ((alignedPtr & bitMask) != 0) {
- alignedPtr += sizeof(void*);
- }
+ // The return pointer will be the next aligned location that is at
+ // least sizeof(void*) after the true pointer. We need the padding
+ // to have a place to write the redirect pointer.
+ size_t alignedPtr = truePtr + sizeof(void*);
- debugAssert(alignedPtr - truePtr + bytes <= totalBytes);
+ const size_t remainder = alignedPtr & bitMask;
+
+ // Add what we need to make it to the next alignment boundary, but
+ // if the remainder was zero, let it wrap to zero and don't add
+ // anything.
+ alignedPtr += ((alignment - remainder) & bitMask);
+
+ debugAssert((alignedPtr & bitMask) == 0);
+ debugAssert((alignedPtr - truePtr + bytes) <= totalBytes);
// Immediately before the aligned location, write the true array location
// so that we can free it correctly.
@@ -1510,8 +1534,10 @@ void* System::alignedMalloc(size_t bytes, size_t alignment) {
debugAssert(isValidHeapPointer((void*)truePtr));
- #ifdef G3D_WIN32
- debugAssert( _CrtIsValidPointer((void*)alignedPtr, bytes, TRUE) );
+ #if defined(G3D_WINDOWS) && defined(G3D_DEBUG)
+ if (bytes < 0xFFFFFFFF) {
+ debugAssert( _CrtIsValidPointer((void*)alignedPtr, (int)bytes, TRUE) );
+ }
#endif
return (void *)alignedPtr;
}
@@ -1539,7 +1565,7 @@ void System::alignedFree(void* _ptr) {
void System::setEnv(const std::string& name, const std::string& value) {
std::string cmd = name + "=" + value;
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
_putenv(cmd.c_str());
# else
// Many linux implementations of putenv expect char*
@@ -1590,7 +1616,7 @@ void System::describeSystem(
{
var(t, "Name", System::currentProgramFilename());
char cwd[1024];
- getcwd(cwd, 1024);
+ (void)getcwd(cwd, 1024);
var(t, "cwd", std::string(cwd));
}
t.popIndent();
@@ -1633,8 +1659,10 @@ void System::describeSystem(
t.writeNewline();
t.pushIndent();
{
+ const char* g3dPath = getenv("G3D9DATA");
var(t, "Link version", G3D_VER);
var(t, "Compile version", System::version());
+ var(t, "G3D9DATA", std::string(g3dPath ? g3dPath : ""));
}
t.popIndent();
t.writeSymbols("}");
@@ -1642,49 +1670,6 @@ void System::describeSystem(
t.writeNewline();
}
-
-void System::setClipboardText(const std::string& s) {
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, s.size() + 1);
- if (hMem) {
- char *pMem = (char*)GlobalLock(hMem);
- strcpy(pMem, s.c_str());
- GlobalUnlock(hMem);
-
- EmptyClipboard();
- SetClipboardData(CF_TEXT, hMem);
- }
-
- CloseClipboard();
- GlobalFree(hMem);
- }
-# endif
-}
-
-
-std::string System::getClipboardText() {
- std::string s;
-
-# ifdef G3D_WIN32
- if (OpenClipboard(NULL)) {
- HANDLE h = GetClipboardData(CF_TEXT);
-
- if (h) {
- char* temp = (char*)GlobalLock(h);
- if (temp) {
- s = temp;
- }
- temp = NULL;
- GlobalUnlock(h);
- }
- CloseClipboard();
- }
-# endif
- return s;
-}
-
-
std::string System::currentDateString() {
time_t t1;
::time(&t1);
@@ -1692,46 +1677,23 @@ std::string System::currentDateString() {
return format("%d-%02d-%02d", t->tm_year + 1900, t->tm_mon + 1, t->tm_mday);
}
-#ifdef _MSC_VER
-
-// VC on Intel
-void System::cpuid(CPUIDFunction func, uint32& areg, uint32& breg, uint32& creg, uint32& dreg) {
-#if !defined(G3D_64BIT) && !defined(__MINGW32__) /* G3DFIX: Don't check if on 64-bit platforms or using MinGW */
- // Can't copy from assembler direct to a function argument (which is on the stack) in VC.
- uint32 a,b,c,d;
-
- // Intel assembler syntax
- __asm {
- mov eax, func // eax <- func
- mov ecx, 0
- cpuid
- mov a, eax
- mov b, ebx
- mov c, ecx
- mov d, edx
- }
- areg = a;
- breg = b;
- creg = c;
- dreg = d;
-#else
- int CPUInfo[4];
- __cpuid(CPUInfo, func);
- memcpy(&areg, &CPUInfo[0], 4);
- memcpy(&breg, &CPUInfo[1], 4);
- memcpy(&creg, &CPUInfo[2], 4);
- memcpy(&dreg, &CPUInfo[3], 4);
-#endif
+std::string System::currentTimeString() {
+ time_t t1;
+ ::time(&t1);
+ tm* t = localtime(&t1);
+ return format("%02d:%02d:%02d", t->tm_hour, t->tm_min, t->tm_sec);
}
-#elif defined(G3D_OSX) && ! defined(G3D_OSX_INTEL)
+#if defined(_MSC_VER)
-// non-intel OS X; no CPUID
+// Windows 64-bit
void System::cpuid(CPUIDFunction func, uint32& eax, uint32& ebx, uint32& ecx, uint32& edx) {
- eax = 0;
- ebx = 0;
- ecx = 0;
- edx = 0;
+ int regs[4] = {eax, ebx, ecx, edx};
+ __cpuid(regs, func);
+ eax = regs[0];
+ ebx = regs[1];
+ ecx = regs[2];
+ edx = regs[3];
}
#else
diff --git a/dep/g3dlite/source/TextInput.cpp b/dep/g3dlite/source/TextInput.cpp
index 354d0de13c0..6f74d93381a 100644
--- a/dep/g3dlite/source/TextInput.cpp
+++ b/dep/g3dlite/source/TextInput.cpp
@@ -1,23 +1,22 @@
/**
- @file TextInput.cpp
+ \file G3D/source/TextInput.cpp
- @author Morgan McGuire, graphics3d.com
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @cite Based on a lexer written by Aaron Orenstein.
+ \cite Based on a lexer written by Aaron Orenstein.
- @created 2001-11-27
- @edited 2010-07-03
+ \created 2001-11-27
+ \edited 2012-07-22
*/
#include "G3D/fileutils.h"
#include "G3D/TextInput.h"
#include "G3D/BinaryInput.h"
+#include "G3D/FileSystem.h"
#include "G3D/stringutils.h"
#ifdef _MSC_VER
# pragma warning (push)
-// conversion from 'int' to 'char', possible loss of data (TODO: fix underlying problems)
-# pragma warning (disable: 4244)
#endif
namespace G3D {
@@ -46,15 +45,15 @@ bool TextInput::parseBoolean(const std::string& _string) {
double TextInput::parseNumber(const std::string& _string) {
std::string s = toLower(_string);
- if (s == "-1.#ind00" || s == "nan") {
+ if (s == "-1.#ind00" || s == "-1.#ind" || s == "nan" || s == "NaN") {
return nan();
}
- if (s == "1.#inf00" || s == "inf" || s == "+inf") {
+ if (s == "1.#inf00" || s == "1.#inf" || s == "inf" || s == "+inf" || s == "Infinity") {
return inf();
}
- if (s == "-1.#inf00" || s == "-inf") {
+ if (s == "-1.#inf00" || s == "-1.#inf" || s == "-inf" || s == "-Infinity") {
return -inf();
}
@@ -99,7 +98,8 @@ TextInput::Settings::Settings () :
Token TextInput::peek() {
if (stack.size() == 0) {
- Token t = nextToken();
+ Token t;
+ nextToken(t);
push(t);
}
@@ -118,18 +118,23 @@ int TextInput::peekCharacterNumber() {
Token TextInput::read() {
+ Token t;
+ read(t);
+ return t;
+}
+
+
+void TextInput::read(Token& t) {
if (stack.size() > 0) {
- Token t = stack.front();
+ t = stack.front();
stack.pop_front();
- return t;
} else {
- return nextToken();
+ nextToken(t);
}
}
-
-std::string TextInput::readUntilNewlineAsString() {
+std::string TextInput::readUntilDelimiterAsString(const char delimiter1, const char delimiter2) {
/*
// Reset the read position back to the start of that token
currentCharOffset = t.bytePosition();
@@ -144,11 +149,21 @@ std::string TextInput::readUntilNewlineAsString() {
*/
std::string s;
- // Read until newline or eof
- char c = '\0';
- do {
- c = buffer[currentCharOffset];
- if (c == '\r' || c == '\n') {
+ if (stack.size() > 0) {
+ // Need to back up. This only works if the stack is actually
+ // in proper order reflecting the real file, and doesn't
+ // contain incorrectly pushed elements.
+ Token t = stack.back();
+ stack.clear();
+ currentCharOffset = (int)t.bytePosition();
+ lineNumber = t.line();
+ charNumber = t.character();
+ }
+
+ // Read until delimiter or eof
+ while (currentCharOffset < buffer.size()) {
+ const char c = buffer[currentCharOffset];
+ if ((c == delimiter1) || (c == delimiter2)) {
// Done
break;
} else {
@@ -156,12 +171,17 @@ std::string TextInput::readUntilNewlineAsString() {
++currentCharOffset;
++charNumber;
}
- } while (currentCharOffset < buffer.size());
+ }
return s;
}
+std::string TextInput::readUntilNewlineAsString() {
+ return readUntilDelimiterAsString('\r', '\n');
+}
+
+
static void toUpper(Set<std::string>& set) {
Array<std::string> symbols;
set.getMembers(symbols);
@@ -240,8 +260,7 @@ int TextInput::peekInputChar(int distance) {
}
-Token TextInput::nextToken() {
- Token t;
+void TextInput::nextToken(Token& t) {
t._bytePosition = currentCharOffset;
t._line = lineNumber;
@@ -251,7 +270,7 @@ Token TextInput::nextToken() {
int c = peekInputChar();
if (c == EOF) {
- return t;
+ return;
}
// loop through white space, newlines and comments
@@ -276,7 +295,7 @@ Token TextInput::nextToken() {
}
eatInputChar();
- return t;
+ return;
} else {
// Consume the single whitespace
c = eatAndPeekInputChar();
@@ -288,8 +307,24 @@ Token TextInput::nextToken() {
t._character = charNumber;
t._bytePosition = currentCharOffset;
+ if (isDigit(c)) {
+ // This is an unsigned number. Jump ahead for fast number reading.
+ goto numLabel;
+ }
+
int c2 = peekInputChar(1);
+ if ((c == '-') && isDigit(c2) && options.signedNumbers) {
+ // This is a simple number. Jump ahead for fast number reading.
+ // We treat this case specially because large (i.e., slow) files
+ // are usually large because they are full of numbers.
+ t._string = "-";
+ c = c2;
+ // Consume the minus sign
+ eatInputChar();
+ goto numLabel;
+ }
+
// parse comments and generate tokens if enabled
std::string commentString;
@@ -327,7 +362,7 @@ Token TextInput::nextToken() {
t._type = Token::COMMENT;
t._extendedType = Token::LINE_COMMENT_TYPE;
t._string = commentString;
- return t;
+ return;
} else {
// There is whitespace after the comment (in particular, the
// newline that terminates the comment). There might also be
@@ -364,7 +399,7 @@ Token TextInput::nextToken() {
t._type = Token::COMMENT;
t._extendedType = Token::BLOCK_COMMENT_TYPE;
t._string = commentString;
- return t;
+ return;
} else {
// There is whitespace after the comment (in particular, the
// newline that terminates the comment). There might also be
@@ -381,7 +416,7 @@ Token TextInput::nextToken() {
// handle EOF
if (c == EOF) {
- return t;
+ return;
}
// Extended ASCII parses as itself, except for EOF
@@ -420,7 +455,7 @@ Token TextInput::nextToken() {
case '?':
case '%':
SETUP_SYMBOL(c);
- return t;
+ return;
case '-': // negative number, -, --, -=, or ->
SETUP_SYMBOL(c);
@@ -431,7 +466,7 @@ Token TextInput::nextToken() {
case '=': // -=
t._string += c;
eatInputChar();
- return t;
+ return;
}
if (options.signedNumbers) {
@@ -451,14 +486,14 @@ Token TextInput::nextToken() {
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
- return t;
+ return;
}
}
}
// plain -
- return t;
+ return;
case '+': // positive number, +, ++, or +=
SETUP_SYMBOL(c);
@@ -468,7 +503,7 @@ Token TextInput::nextToken() {
case '=': // +=
t._string += c;
eatInputChar();
- return t;
+ return;
}
if (options.signedNumbers) {
@@ -488,12 +523,12 @@ Token TextInput::nextToken() {
eatInputChar(); // i
eatInputChar(); // n
eatInputChar(); // f
- return t;
+ return;
}
}
}
- return t;
+ return;
case ':': // : or :: or ::> or ::= or := or :>
SETUP_SYMBOL(c);
@@ -510,12 +545,11 @@ Token TextInput::nextToken() {
eatInputChar();
}
}
- }
- else if (options.proofSymbols && (c == '=' || c == '>')) {
+ } else if (options.proofSymbols && (c == '=' || c == '>')) {
t._string += c;
eatInputChar();
}
- return t;
+ return;
case '=': // = or == or =>
SETUP_SYMBOL(c);
@@ -523,13 +557,11 @@ Token TextInput::nextToken() {
if (c == '=') {
t._string += c;
eatInputChar();
- return t;
} else if (options.proofSymbols && (c == '>')) {
t._string += c;
eatInputChar();
- return t;
}
- return t;
+ return;
case '*': // * or *=
case '/': // / or /=
@@ -541,9 +573,8 @@ Token TextInput::nextToken() {
if (c == '=') {
t._string += c;
eatInputChar();
- return t;
}
- return t;
+ return;
case '>': // >, >>,or >=
case '<': // <<, <<, or <= or <- or <:
@@ -556,7 +587,6 @@ Token TextInput::nextToken() {
if ((c == '=') || (orig_c == c)) {
t._string += c;
eatInputChar();
- return t;
} else if (options.proofSymbols) {
if ((orig_c == '<') && (c == '-')) {
t._string += c;
@@ -576,7 +606,7 @@ Token TextInput::nextToken() {
}
}
}
- return t;
+ return;
case '\\': // backslash or escaped comment char.
SETUP_SYMBOL(c);
@@ -591,9 +621,9 @@ Token TextInput::nextToken() {
t._string = c;
eatInputChar();
- return t;
+ return;
}
- return t;
+ return;
case '.': // number, ., .., or ...
if (isDigit(peekInputChar(1))) {
@@ -611,10 +641,10 @@ Token TextInput::nextToken() {
t._string += c;
eatInputChar();
}
- return t;
+ return;
}
- return t;
+ return;
} // switch (c)
@@ -640,7 +670,7 @@ numLabel:
} else {
t._extendedType = Token::INTEGER_TYPE;
}
-
+
if ((c == '0') && (peekInputChar(1) == 'x')) {
// Hex number
t._string += "0x";
@@ -656,7 +686,7 @@ numLabel:
}
} else {
- // Non-hex number
+ // Non-hex number
// Read the part before the decimal.
while (isDigit(c)) {
@@ -681,6 +711,7 @@ numLabel:
isSpecial = true;
// We are reading a floating point special value
// of the form -1.#IND00, -1.#INF00, or 1.#INF00
+ // (with or without the trailing 00
c = eatAndPeekInputChar();
char test = c;
if (! options.caseSensitive) {
@@ -718,16 +749,25 @@ numLabel:
t.line(), charNumber);
}
t._string += c;
+
+ // On older systems, there may be an extra 00 tacked on.
for (int j = 0; j < 2; ++j) {
c = eatAndPeekInputChar();
- if (c != '0') {
- throw BadMSVCSpecial
+ if (c == '0') {
+ c = eatAndPeekInputChar();
+ if (c != '0') {
+ throw BadMSVCSpecial
(
- "Incorrect floating-point special (inf or"
- "nan) format.",
- t.line(), charNumber);
+ "Incorrect floating-point special (inf or nan) "
+ "format.",
+ t.line(), charNumber);
+ } else {
+ eatInputChar();
+ t._string += "00";
+ }
+ } else {
+ break;
}
- t._string += (char)c;
}
} else {
@@ -763,7 +803,7 @@ numLabel:
c = eatAndPeekInputChar();
}
}
- return t;
+ return;
} else if (isLetter(c) || (c == '_')) {
// Identifier or keyword
@@ -798,7 +838,7 @@ numLabel:
t._type = Token::NUMBER;
t._extendedType = Token::FLOATING_POINT_TYPE;
}
- return t;
+ return;
} else if (c == '\"') {
@@ -807,7 +847,7 @@ numLabel:
// Double quoted string
parseQuotedString('\"', t);
- return t;
+ return;
} else if (c == options.singleQuoteCharacter) {
@@ -822,22 +862,20 @@ numLabel:
t._type = Token::SYMBOL;
t._extendedType = Token::SYMBOL_TYPE;
}
- return t;
+ return;
} // end of special case tokens
- if (c == EOF) {
+ if ((c == EOF) || (c == '\0')) {
t._type = Token::END;
t._extendedType = Token::END_TYPE;
t._string = "";
- return t;
+ return;
}
// Some unknown token
- debugAssertM(false,
- format("Unrecognized token type beginning with character '%c' (ASCII %d)",
- c, c));
- return t;
+ throw format("Unrecognized token type beginning with character '%c' (ASCII %d)", c, c);
+ return;
}
@@ -915,8 +953,9 @@ void TextInput::parseQuotedString(unsigned char delimiter, Token& t) {
}
}
+
bool TextInput::readBoolean() {
- Token t(read());
+ const Token& t = read();
if (t._type == Token::BOOLEAN) {
return t.boolean();
@@ -930,10 +969,53 @@ bool TextInput::readBoolean() {
Token::BOOLEAN, t._type);
}
+
+int TextInput::readInteger() {
+ Token t;
+ read(t);
+
+ if (t._extendedType == Token::INTEGER_TYPE) { // common case
+ return int(t.number());
+ } else {
+ // Even if signedNumbers is disabled, readInteger attempts to
+ // read a signed number, so we handle that case here.
+ if (! options.signedNumbers
+ && (t._type == Token::SYMBOL)
+ && ((t._string == "-")
+ || (t._string == "+"))) {
+
+ Token t2;
+ read(t2);
+
+ if ((t2._extendedType == Token::INTEGER_TYPE)
+ && (t2._character == t._character + 1)) {
+
+ if (t._string == "-") {
+ return (int)-t2.number();
+ } else {
+ return (int)t2.number();
+ }
+ }
+
+ // push back the second token.
+ push(t2);
+ }
+
+ // Push initial token back, and throw an error. We intentionally
+ // indicate that the wrong type is the type of the initial token.
+ // Logically, the number started there.
+ push(t);
+ throw WrongTokenType(options.sourceFileName, t.line(), t.character(),
+ Token::NUMBER, t._type);
+ }
+}
+
+
double TextInput::readNumber() {
- Token t(read());
+ Token t;
+ read(t);
- if (t._type == Token::NUMBER) {
+ if (t._type == Token::NUMBER) { // common case
return t.number();
}
@@ -970,7 +1052,8 @@ double TextInput::readNumber() {
Token TextInput::readStringToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::STRING) { // fast path
return t;
@@ -985,8 +1068,9 @@ std::string TextInput::readString() {
return readStringToken()._string;
}
+
void TextInput::readString(const std::string& s) {
- Token t(readStringToken());
+ const Token& t = readStringToken();
if (t._string == s) { // fast path
return;
@@ -997,8 +1081,10 @@ void TextInput::readString(const std::string& s) {
s, t._string);
}
+
Token TextInput::readCommentToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::COMMENT) { // fast path
return t;
@@ -1009,12 +1095,14 @@ Token TextInput::readCommentToken() {
Token::COMMENT, t._type);
}
+
std::string TextInput::readComment() {
return readCommentToken()._string;
}
+
void TextInput::readComment(const std::string& s) {
- Token t(readCommentToken());
+ const Token& t = readCommentToken();
if (t._string == s) { // fast path
return;
@@ -1025,8 +1113,10 @@ void TextInput::readComment(const std::string& s) {
s, t._string);
}
+
Token TextInput::readNewlineToken() {
- Token t(read());
+ Token t;
+ read(t);
if (t._type == Token::NEWLINE) { // fast path
return t;
@@ -1042,7 +1132,7 @@ std::string TextInput::readNewline() {
}
void TextInput::readNewline(const std::string& s) {
- Token t(readNewlineToken());
+ const Token& t = readNewlineToken();
if (t._string == s) { // fast path
return;
@@ -1053,11 +1143,19 @@ void TextInput::readNewline(const std::string& s) {
s, t._string);
}
+
Token TextInput::readSymbolToken() {
- Token t(read());
+ Token t;
+ readSymbolToken(t);
+ return t;
+}
+
+
+void TextInput::readSymbolToken(Token& t) {
+ read(t);
if (t._type == Token::SYMBOL) { // fast path
- return t;
+ return;
}
push(t);
@@ -1070,10 +1168,12 @@ std::string TextInput::readSymbol() {
return readSymbolToken()._string;
}
+
void TextInput::readSymbol(const std::string& symbol) {
- Token t(readSymbolToken());
+ Token t;
+ readSymbolToken(t);
- if (t._string == symbol) { // fast path
+ if (t._string == symbol) { // fast path
return;
}
@@ -1085,29 +1185,53 @@ void TextInput::readSymbol(const std::string& symbol) {
TextInput::TextInput(const std::string& filename, const Settings& opt) : options(opt) {
init();
- std::string input = readWholeFile(filename);
-
if (options.sourceFileName.empty()) {
options.sourceFileName = filename;
}
- int n = input.size();
- buffer.resize(n);
- System::memcpy(buffer.getCArray(), input.c_str(), n);
+
+ std::string zipfile;
+ if (FileSystem::inZipfile(filename, zipfile)) {
+ // TODO: this could be faster if we directly read the zipfile
+ const std::string& input = readWholeFile(filename);
+ size_t n = input.size();
+ buffer.resize(n);
+ System::memcpy(buffer.getCArray(), input.c_str(), n);
+ } else {
+ // Read directly into the array
+ const uint64 n = FileSystem::size(filename);
+ alwaysAssertM(n != uint64(-1), std::string("File does not exist: ") + filename);
+ buffer.resize(size_t(n));
+ FILE* f = FileSystem::fopen(filename.c_str(), "rb");
+ fread(buffer.getCArray(), 1, size_t(n), f);
+ FileSystem::fclose(f);
+ }
}
-TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) : options(opt) {
- (void)fs;
+void TextInput::initFromString(const char* str, int len, const Settings& settings) {
+ options = settings;
init();
if (options.sourceFileName.empty()) {
- if (str.length() < 14) {
- options.sourceFileName = std::string("\"") + str + "\"";
+ if (len < 14) {
+ options.sourceFileName = format("\"%.*s\"", len, str);
} else {
- options.sourceFileName = std::string("\"") + str.substr(0, 10) + "...\"";
+ options.sourceFileName = format("\"%.*s...\"", 10, str);
}
}
- buffer.resize(str.length()); // we don't bother copying trailing NUL.
- System::memcpy(buffer.getCArray(), str.c_str(), buffer.size());
+ buffer.resize(len);
+ System::memcpy(buffer.getCArray(), str, buffer.size());
+}
+
+
+TextInput::TextInput(FS fs, const std::string& str, const Settings& opt) {
+ (void)fs;
+ initFromString(str.c_str(), (int)str.size(), opt);
+}
+
+
+TextInput::TextInput(FS fs, const char* str, size_t len, const Settings& opt) : options(opt) {
+ (void)fs;
+ initFromString(str, (int)len, opt);
}
diff --git a/dep/g3dlite/source/TextOutput.cpp b/dep/g3dlite/source/TextOutput.cpp
index 3257f6fb9ce..e764b59c7d6 100644
--- a/dep/g3dlite/source/TextOutput.cpp
+++ b/dep/g3dlite/source/TextOutput.cpp
@@ -1,11 +1,11 @@
/**
- @file TextOutput.cpp
+ \file G3D.lib/source/TextOutput.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2004-06-21
- @edited 2010-03-14
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \created 2004-06-21
+ \edited 2013-04-09
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2013, Morgan McGuire.
All rights reserved.
*/
@@ -17,11 +17,12 @@
namespace G3D {
TextOutput::TextOutput(const TextOutput::Settings& opt) :
- startingNewLine(true),
+ startingNewLine(true),
currentColumn(0),
- inDQuote(false),
- filename(""),
- indentLevel(0)
+ inDQuote(false),
+ filename(""),
+ indentLevel(0),
+ m_currentLine(0)
{
setOptions(opt);
}
@@ -30,9 +31,10 @@ TextOutput::TextOutput(const TextOutput::Settings& opt) :
TextOutput::TextOutput(const std::string& fil, const TextOutput::Settings& opt) :
startingNewLine(true),
currentColumn(0),
- inDQuote(false),
- filename(fil),
- indentLevel(0)
+ inDQuote(false),
+ filename(fil),
+ indentLevel(0),
+ m_currentLine(0)
{
setOptions(opt);
@@ -106,9 +108,17 @@ static std::string escape(const std::string& string) {
return result;
}
+
void TextOutput::writeString(const std::string& string) {
+ // Never break a line in a string
+ const Settings::WordWrapMode old = option.wordWrap;
+
+ if (! option.allowWordWrapInsideDoubleQuotes) {
+ option.wordWrap = Settings::WRAP_NONE;
+ }
// Convert special characters to escape sequences
this->printf("\"%s\"", escape(string).c_str());
+ option.wordWrap = old;
}
@@ -117,7 +127,7 @@ void TextOutput::writeBoolean(bool b) {
}
void TextOutput::writeNumber(double n) {
- this->printf("%f ", n);
+ this->printf("%g ", n);
}
@@ -128,11 +138,14 @@ void TextOutput::writeNumber(int n) {
void TextOutput::writeSymbol(const std::string& string) {
if (string.size() > 0) {
- // TODO: check for legal symbols?
this->printf("%s ", string.c_str());
}
}
+void TextOutput::writeSymbol(char c) {
+ this->printf("%c ", c);
+}
+
void TextOutput::writeSymbols(
const std::string& a,
const std::string& b,
@@ -166,6 +179,17 @@ void TextOutput::printf(const char* formatString, ...) {
}
+bool TextOutput::deleteSpace() {
+ if ((currentColumn > 0) && (data.last() == ' ')) {
+ data.popDiscard();
+ --currentColumn;
+ return true;
+ } else {
+ return false;
+ }
+}
+
+
void TextOutput::convertNewlines(const std::string& in, std::string& out) {
// TODO: can be significantly optimized in cases where
// single characters are copied in order by walking through
@@ -256,20 +280,20 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// search backwards for a space, then execute case 2.
// Index of most recent space
- uint32 lastSpace = data.size() - 1;
+ size_t lastSpace = data.size() - 1;
// How far back we had to look for a space
- uint32 k = 0;
- uint32 maxLookBackward = currentColumn - indentSpaces;
+ size_t k = 0;
+ size_t maxLookBackward = currentColumn - indentSpaces;
// Search backwards (from current character), looking for a space.
while ((k < maxLookBackward) &&
- (lastSpace > 0) &&
- (! ((data[lastSpace] == ' ') && unquotedSpace))) {
+ (lastSpace > 0) &&
+ (! ((data[(int)lastSpace] == ' ') && unquotedSpace))) {
--lastSpace;
++k;
- if ((data[lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
+ if ((data[(int)lastSpace] == '\"') && !option.allowWordWrapInsideDoubleQuotes) {
unquotedSpace = ! unquotedSpace;
}
}
@@ -296,10 +320,10 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// Find the start of the spaces. firstSpace is the index of the
// first non-space, looking backwards from lastSpace.
- uint32 firstSpace = lastSpace;
+ size_t firstSpace = lastSpace;
while ((k < maxLookBackward) &&
(firstSpace > 0) &&
- (data[firstSpace] == ' ')) {
+ (data[(int)firstSpace] == ' ')) {
--firstSpace;
++k;
}
@@ -323,8 +347,8 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
// Copy over the characters that should be saved
Array<char> temp;
- for (uint32 j = lastSpace + 1; j < (uint32)data.size(); ++j) {
- char c = data[j];
+ for (size_t j = lastSpace + 1; j < (uint32)data.size(); ++j) {
+ char c = data[(int)j];
if (c == '\"') {
// Undo changes to quoting (they will be re-done
@@ -339,8 +363,8 @@ void TextOutput::wordWrapIndentAppend(const std::string& str) {
writeNewline();
// Write them back
- for (uint32 j = 0; j < (uint32)temp.size(); ++j) {
- indentAppend(temp[j]);
+ for (size_t j = 0; j < (uint32)temp.size(); ++j) {
+ indentAppend(temp[(int)j]);
}
// We are now free to continue adding from the
@@ -378,12 +402,13 @@ void TextOutput::indentAppend(char c) {
startingNewLine = (c == '\n');
if (startingNewLine) {
currentColumn = 0;
+ ++m_currentLine;
}
}
void TextOutput::vprintf(const char* formatString, va_list argPtr) {
- std::string str = vformat(formatString, argPtr);
+ const std::string& str = vformat(formatString, argPtr);
std::string clean;
convertNewlines(str, clean);
diff --git a/dep/g3dlite/source/ThreadSet.cpp b/dep/g3dlite/source/ThreadSet.cpp
index ee3895fe9de..df6fd4d4721 100644
--- a/dep/g3dlite/source/ThreadSet.cpp
+++ b/dep/g3dlite/source/ThreadSet.cpp
@@ -1,4 +1,5 @@
#include "G3D/ThreadSet.h"
+#include "G3D/GThread.h"
namespace G3D {
@@ -25,7 +26,7 @@ int ThreadSet::numStarted() const {
}
-void ThreadSet::start(GThread::SpawnBehavior lastBehavior) const {
+void ThreadSet::start(SpawnBehavior lastBehavior) const {
ThreadSet* me = const_cast<ThreadSet*>(this);
Array<GThreadRef> unstarted;
@@ -38,20 +39,22 @@ void ThreadSet::start(GThread::SpawnBehavior lastBehavior) const {
}
int last = unstarted.size();
- if (lastBehavior == GThread::USE_CURRENT_THREAD) {
+ if (lastBehavior == USE_CURRENT_THREAD) {
// Save the last unstarted for the current thread
--last;
}
+ // Start all threads
for (int i = 0; i < last; ++i) {
- unstarted[i]->start(GThread::USE_NEW_THREAD);
+ unstarted[i]->start(USE_NEW_THREAD);
}
me->m_lock.unlock();
// Start the last one on my thread
- if ((unstarted.size() > 0) && (lastBehavior == GThread::USE_CURRENT_THREAD)) {
- unstarted.last()->start(GThread::USE_CURRENT_THREAD);
+ if ((unstarted.size() > 0) && (lastBehavior == USE_CURRENT_THREAD)) {
+ unstarted.last()->start(USE_CURRENT_THREAD);
+ debugAssert(unstarted.last()->completed());
}
}
@@ -70,6 +73,7 @@ void ThreadSet::terminate() const {
void ThreadSet::waitForCompletion() const {
ThreadSet* me = const_cast<ThreadSet*>(this);
+
me->m_lock.lock();
for (int i = 0; i < m_thread.size(); ++i) {
if (m_thread[i]->started()) {
diff --git a/dep/g3dlite/source/Triangle.cpp b/dep/g3dlite/source/Triangle.cpp
index 253438ad5fb..e1b5f8e051b 100644
--- a/dep/g3dlite/source/Triangle.cpp
+++ b/dep/g3dlite/source/Triangle.cpp
@@ -172,7 +172,7 @@ bool Triangle::intersect(const Ray& ray, float& distance, float baryCoord[3]) co
// This is a new hit, closer than the previous one
distance = t;
- baryCoord[0] = 1.0 - u - v;
+ baryCoord[0] = 1.0f - u - v;
baryCoord[1] = u;
baryCoord[2] = v;
diff --git a/dep/g3dlite/source/UprightFrame.cpp b/dep/g3dlite/source/UprightFrame.cpp
index c80264bf4e8..80c7e24023d 100644
--- a/dep/g3dlite/source/UprightFrame.cpp
+++ b/dep/g3dlite/source/UprightFrame.cpp
@@ -1,11 +1,7 @@
/**
- @file UprightFrame.cpp
- Box class
+ \file UprightFrame.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
-
- @created 2007-05-02
- @edited 2007-05-05
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
*/
#include "G3D/UprightFrame.h"
@@ -17,12 +13,38 @@ namespace G3D {
UprightFrame::UprightFrame(const CoordinateFrame& cframe) {
Vector3 look = cframe.lookVector();
- yaw = G3D::pi() + atan2(look.x, look.z);
+ yaw = (float)(G3D::pi() + atan2(look.x, look.z));
pitch = asin(look.y);
translation = cframe.translation;
}
+
+UprightFrame::UprightFrame(const Any& any) {
+ any.verifyName("UprightFrame");
+ any.verifyType(Any::TABLE);
+
+ translation = any["translation"];
+ pitch = any["pitch"];
+ yaw = any["yaw"];
+}
+
+
+Any UprightFrame::toAny() const {
+ Any any(Any::TABLE, "UprightFrame");
+
+ any["translation"] = translation;
+ any["pitch"] = pitch;
+ any["yaw"] = yaw;
+
+ return any;
+}
+
+
+UprightFrame& UprightFrame::operator=(const Any& any) {
+ *this = UprightFrame(any);
+ return *this;
+}
CoordinateFrame UprightFrame::toCoordinateFrame() const {
CoordinateFrame cframe;
@@ -59,15 +81,15 @@ void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
// to be interpolated the long way.
// Find canonical [0, 2pi] versions of these numbers
- float p = wrap(prev, twoPi());
- float c = wrap(cur, twoPi());
+ float p = (float)wrap(prev, twoPi());
+ float c = (float)wrap(cur, twoPi());
// Find the difference -pi < diff < pi between the current and previous values
float diff = c - p;
if (diff < -G3D::pi()) {
- diff += twoPi();
+ diff += (float)twoPi();
} else if (diff > G3D::pi()) {
- diff -= twoPi();
+ diff -= (float)twoPi();
}
// Offset the current from the previous by the difference
@@ -77,7 +99,6 @@ void UprightFrame::unwrapYaw(UprightFrame* a, int N) {
}
}
-
void UprightFrame::serialize(class BinaryOutput& b) const {
translation.serialize(b);
b.writeFloat32(pitch);
@@ -91,9 +112,70 @@ void UprightFrame::deserialize(class BinaryInput& b) {
yaw = b.readFloat32();
}
+///////////////////////////////////////////////////////////////////////////////////////////
+
+UprightSpline::UprightSpline() : Spline<UprightFrame>() {
+}
+
+
+UprightSpline::UprightSpline(const Any& any) {
+ any.verifyName("UprightSpline");
+ any.verifyType(Any::TABLE);
+
+ extrapolationMode = any["extrapolationMode"];
+
+ const Any& controlsAny = any["control"];
+ controlsAny.verifyType(Any::ARRAY);
+
+ control.resize(controlsAny.length());
+ for (int controlIndex = 0; controlIndex < control.length(); ++controlIndex) {
+ control[controlIndex] = controlsAny[controlIndex];
+ }
+
+ const Any& timesAny = any["time"];
+ timesAny.verifyType(Any::ARRAY);
+
+ time.resize(timesAny.length());
+ for (int timeIndex = 0; timeIndex < time.length(); ++timeIndex) {
+ time[timeIndex] = timesAny[timeIndex];
+ }
+}
+
+
+Any UprightSpline::toAny(const std::string& myName) const {
+ Any any(Any::TABLE, myName);
+
+ any["extrapolationMode"] = extrapolationMode;
+
+ Any controlsAny(Any::ARRAY);
+ for (int controlIndex = 0; controlIndex < control.length(); ++controlIndex) {
+ controlsAny.append(control[controlIndex]);
+ }
+ any["control"] = controlsAny;
+
+ Any timesAny(Any::ARRAY);
+ for (int timeIndex = 0; timeIndex < time.length(); ++timeIndex) {
+ timesAny.append(Any(time[timeIndex]));
+ }
+ any["time"] = timesAny;
+
+ return any;
+}
+
+
+Any UprightSpline::toAny() const {
+ return toAny("UprightSpline");
+}
+
+
+UprightSpline& UprightSpline::operator=(const Any& any) {
+ *this = UprightSpline(any);
+ return *this;
+}
+
void UprightSpline::serialize(class BinaryOutput& b) const {
- b.writeBool8(cyclic);
+ b.writeInt32(extrapolationMode);
b.writeInt32(control.size());
for (int i = 0; i < control.size(); ++i) {
@@ -107,7 +189,7 @@ void UprightSpline::serialize(class BinaryOutput& b) const {
void UprightSpline::deserialize(class BinaryInput& b) {
- cyclic = b.readBool8();
+ extrapolationMode = SplineExtrapolationMode(b.readInt32());
control.resize(b.readInt32());
for (int i = 0; i < control.size(); ++i) {
@@ -124,7 +206,7 @@ void UprightSpline::deserialize(class BinaryInput& b) {
// Import legacy path
time.resize(control.size());
for (int i = 0; i < time.size(); ++i) {
- time[i] = i;
+ time[i] = (float)i;
}
}
}
diff --git a/dep/g3dlite/source/Vector2.cpp b/dep/g3dlite/source/Vector2.cpp
index ec0737c3755..a6edea9a83f 100644
--- a/dep/g3dlite/source/Vector2.cpp
+++ b/dep/g3dlite/source/Vector2.cpp
@@ -9,12 +9,13 @@
at http://www.magic-software.com
@created 2001-06-02
- @edited 2009-11-16
+ @edited 2010-11-16
*/
#include "G3D/platform.h"
#include <stdlib.h>
#include "G3D/Vector2.h"
+#include "G3D/Vector2int32.h"
#include "G3D/g3dmath.h"
#include "G3D/format.h"
#include "G3D/BinaryInput.h"
@@ -25,9 +26,12 @@
namespace G3D {
+Vector2::Vector2(const Vector2int32& other) : x((float)other.x), y((float)other.y) {
+}
+
Vector2::Vector2(const Any& any) {
- any.verifyName("Vector2");
+ any.verifyName("Vector2", "Point2");
any.verifyType(Any::TABLE, Any::ARRAY);
any.verifySize(2);
@@ -42,7 +46,13 @@ Vector2::Vector2(const Any& any) {
}
-Vector2::operator Any() const {
+Vector2& Vector2::operator=(const Any& a) {
+ *this = Vector2(a);
+ return *this;
+}
+
+
+Any Vector2::toAny() const {
Any any(Any::ARRAY, "Vector2");
any.append(x, y);
return any;
@@ -70,26 +80,26 @@ const Vector2& Vector2::unitY() {
}
const Vector2& Vector2::inf() {
- static Vector2 v((float)G3D::finf(), (float)G3D::finf());
- return v;
+ static Vector2 v(G3D::finf(), G3D::finf());
+ return v;
}
const Vector2& Vector2::nan() {
- static Vector2 v((float)G3D::fnan(), (float)G3D::fnan());
- return v;
+ static Vector2 v(G3D::fnan(), G3D::fnan());
+ return v;
}
const Vector2& Vector2::minFinite() {
- static Vector2 v(-FLT_MAX, -FLT_MAX);
- return v;
+ static Vector2 v(-FLT_MAX, -FLT_MAX);
+ return v;
}
const Vector2& Vector2::maxFinite() {
- static Vector2 v(FLT_MAX, FLT_MAX);
- return v;
+ static Vector2 v(FLT_MAX, FLT_MAX);
+ return v;
}
@@ -145,9 +155,7 @@ Vector2 Vector2::random(G3D::Random& r) {
} while (result.squaredLength() >= 1.0f);
- result.unitize();
-
- return result;
+ return result.direction();
}
@@ -161,20 +169,6 @@ Vector2& Vector2::operator/= (float k) {
return *this;
}
-//----------------------------------------------------------------------------
-float Vector2::unitize (float fTolerance) {
- float fLength = length();
-
- if (fLength > fTolerance) {
- float fInvLength = 1.0f / fLength;
- x *= fInvLength;
- y *= fInvLength;
- } else {
- fLength = 0.0;
- }
-
- return fLength;
-}
//----------------------------------------------------------------------------
@@ -220,5 +214,12 @@ Vector4 Vector2::xyyy() const { return Vector4 (x, y, y, y); }
Vector4 Vector2::yyyy() const { return Vector4 (y, y, y, y); }
+void serialize(const Vector2& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
+
+void deserialize(Vector2& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
} // namespace
diff --git a/dep/g3dlite/source/Vector2int16.cpp b/dep/g3dlite/source/Vector2int16.cpp
index 2a4035a4d09..16893eb1752 100644
--- a/dep/g3dlite/source/Vector2int16.cpp
+++ b/dep/g3dlite/source/Vector2int16.cpp
@@ -1,10 +1,10 @@
/**
- @file Vector2int16.cpp
+ \file G3D/Vector2int16.cpp
- @author Morgan McGuire, http://graphics.cs.williams.edu
+ \author Morgan McGuire, http://graphics.cs.williams.edu
- @created 2003-08-09
- @edited 2006-01-29
+ \created 2003-08-09
+ \edited 2011-01-06
*/
#include "G3D/platform.h"
@@ -13,9 +13,41 @@
#include "G3D/Vector2.h"
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
+#include "G3D/Any.h"
+#include "G3D/Vector2int32.h"
namespace G3D {
+Vector2int16::Vector2int16(const class Vector2int32& v) : x(v.x), y(v.y) {}
+
+Vector2int16::Vector2int16(const Any& any) {
+ any.verifyName("Vector2int16", "Point2int16");
+ any.verifyType(Any::TABLE, Any::ARRAY);
+ any.verifySize(2);
+
+ if (any.type() == Any::ARRAY) {
+ x = any[0];
+ y = any[1];
+ } else {
+ // Table
+ x = any["x"];
+ y = any["y"];
+ }
+}
+
+
+Vector2int16& Vector2int16::operator=(const Any& a) {
+ *this = Vector2int16(a);
+ return *this;
+}
+
+
+Any Vector2int16::toAny() const {
+ Any any(Any::ARRAY, "Vector2int16");
+ any.append(x, y);
+ return any;
+}
+
Vector2int16::Vector2int16(const class Vector2& v) {
x = (int16)iFloor(v.x + 0.5);
y = (int16)iFloor(v.y + 0.5);
diff --git a/dep/g3dlite/source/Vector3.cpp b/dep/g3dlite/source/Vector3.cpp
index 55343e96ece..e2d9643e5cc 100644
--- a/dep/g3dlite/source/Vector3.cpp
+++ b/dep/g3dlite/source/Vector3.cpp
@@ -1,14 +1,14 @@
/**
- @file Vector3.cpp
+ \file G3D.lib/source/Vector3.cpp
3D vector class
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
+ \cite Portions based on Dave Eberly's Magic Software Library at http://www.magic-software.com
- @created 2001-06-02
- @edited 2009-11-27
+ \created 2001-06-02
+ \edited 2011-11-27
*/
#include <limits>
@@ -31,8 +31,39 @@
namespace G3D {
+
+Vector3 Vector3::movedTowards(const Vector3& goal, float maxTranslation) const {
+ Vector3 t = *this;
+ t.moveTowards(goal, maxTranslation);
+ return t;
+}
+
+
+void Vector3::moveTowards(const Vector3& goal, float maxTranslation) {
+ // Apply clamped translation
+ Vector3 dX = goal - *this;
+ float length = dX.length();
+ if ((length < 0.00001f) || (length < maxTranslation)) {
+ *this = goal;
+ } else {
+ *this += G3D::min(1.0f, maxTranslation / length) * dX;
+ }
+}
+
+
Vector3::Vector3(const Any& any) {
- any.verifyName("Vector3");
+ if (any.name() == "Vector3::inf" || any.name() == "Point3::inf") {
+ *this = inf();
+ return;
+ } else if (any.name() == "Vector3::zero" || any.name() == "Point3::zero") {
+ *this = zero();
+ return;
+ } else if (any.name() == "Vector3::nan" || any.name() == "Point3::nan") {
+ *this = nan();
+ return;
+ }
+
+ any.verifyName("Vector3", "Point3");
any.verifyType(Any::TABLE, Any::ARRAY);
any.verifySize(3);
@@ -48,8 +79,25 @@ Vector3::Vector3(const Any& any) {
}
}
-Vector3::operator Any() const {
- Any any(Any::ARRAY, "Vector3");
+
+bool Vector3::isNaN() const {
+ return G3D::isNaN(x) || G3D::isNaN(y) || G3D::isNaN(z);
+}
+
+
+Vector3& Vector3::operator=(const Any& a) {
+ *this = Vector3(a);
+ return *this;
+}
+
+
+Any Vector3::toAny() const {
+ return toAny("Vector3");
+}
+
+
+Any Vector3::toAny(const std::string& name) const {
+ Any any(Any::ARRAY, name);
any.append(x, y, z);
return any;
}
@@ -105,7 +153,11 @@ Vector3::Axis Vector3::primaryAxis() const {
size_t Vector3::hashCode() const {
- return Vector4(*this, 0.0f).hashCode();
+ const uint32* u = (const uint32*)this;
+ return
+ HashTrait<uint32>::hashCode(u[0]) ^
+ HashTrait<uint32>::hashCode(~u[1]) ^
+ HashTrait<uint32>::hashCode((u[2] << 16) | ~(u[2] >> 16));
}
std::ostream& operator<<(std::ostream& os, const Vector3& v) {
@@ -120,7 +172,7 @@ double frand() {
}
Vector3::Vector3(TextInput& t) {
- deserialize(t);
+ deserialize(t);
}
Vector3::Vector3(BinaryInput& b) {
@@ -178,22 +230,6 @@ Vector3 Vector3::random(Random& r) {
}
-float Vector3::unitize(float fTolerance) {
- float fMagnitude = magnitude();
-
- if (fMagnitude > fTolerance) {
- float fInvMagnitude = 1.0f / fMagnitude;
- x *= fInvMagnitude;
- y *= fInvMagnitude;
- z *= fInvMagnitude;
- } else {
- fMagnitude = 0.0f;
- }
-
- return fMagnitude;
-}
-
-
Vector3 Vector3::reflectAbout(const Vector3& normal) const {
Vector3 out;
@@ -224,6 +260,26 @@ Vector3 Vector3::cosHemiRandom(const Vector3& normal, Random& r) {
}
+Vector3 Vector3::cosSphereRandom(const Vector3& normal, Random& r) {
+ debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
+ "cosSphereRandom requires its argument to have unit length");
+
+ float x, y, z;
+ r.cosSphere(x, y, z);
+
+ // Make a coordinate system
+ const Vector3& Z = normal;
+
+ Vector3 X, Y;
+ normal.getTangents(X, Y);
+
+ return
+ x * X +
+ y * Y +
+ z * Z;
+}
+
+
Vector3 Vector3::cosPowHemiRandom(const Vector3& normal, const float k, Random& r) {
debugAssertM(G3D::fuzzyEq(normal.length(), 1.0f),
"cosPowHemiRandom requires its argument to have unit length");
@@ -310,40 +366,20 @@ void Vector3::orthonormalize (Vector3 akVector[3]) {
// product of vectors A and B.
// compute u0
- akVector[0].unitize();
+ akVector[0] = akVector[0].direction();
// compute u1
- float fDot0 = akVector[0].dot(akVector[1]);
+ float fDot0 = akVector[0].dot(akVector[1]);
akVector[1] -= akVector[0] * fDot0;
- akVector[1].unitize();
+ akVector[1] = akVector[1].direction();
// compute u2
- float fDot1 = akVector[1].dot(akVector[2]);
+ float fDot1 = akVector[1].dot(akVector[2]);
fDot0 = akVector[0].dot(akVector[2]);
akVector[2] -= akVector[0] * fDot0 + akVector[1] * fDot1;
- akVector[2].unitize();
+ akVector[2] = akVector[2].direction();
}
-//----------------------------------------------------------------------------
-void Vector3::generateOrthonormalBasis (Vector3& rkU, Vector3& rkV,
- Vector3& rkW, bool bUnitLengthW) {
- if ( !bUnitLengthW )
- rkW.unitize();
-
- if ( G3D::abs(rkW.x) >= G3D::abs(rkW.y)
- && G3D::abs(rkW.x) >= G3D::abs(rkW.z) ) {
- rkU.x = -rkW.y;
- rkU.y = + rkW.x;
- rkU.z = 0.0;
- } else {
- rkU.x = 0.0;
- rkU.y = + rkW.z;
- rkU.z = -rkW.y;
- }
-
- rkU.unitize();
- rkV = rkW.cross(rkU);
-}
//----------------------------------------------------------------------------
@@ -497,8 +533,12 @@ Vector4 Vector3::yzzz() const { return Vector4 (y, z, z, z); }
Vector4 Vector3::zzzz() const { return Vector4 (z, z, z, z); }
+void serialize(const Vector3& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
-
-
+void deserialize(Vector3& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
} // namespace
diff --git a/dep/g3dlite/source/Vector3int16.cpp b/dep/g3dlite/source/Vector3int16.cpp
index 44069b85d8c..3c9c5dc9295 100644
--- a/dep/g3dlite/source/Vector3int16.cpp
+++ b/dep/g3dlite/source/Vector3int16.cpp
@@ -46,4 +46,14 @@ std::string Vector3int16::toString() const {
return G3D::format("(%d, %d, %d)", x, y, z);
}
+
+Vector3int16 Vector3int16::floor(const Vector3& v) {
+ return Vector3int16(iFloor(v.x), iFloor(v.y), iFloor(v.z));
+}
+
+
+Vector3int16 Vector3int16::ceil(const Vector3& v) {
+ return Vector3int16(iCeil(v.x), iCeil(v.y), iCeil(v.z));
+}
+
}
diff --git a/dep/g3dlite/source/Vector3int32.cpp b/dep/g3dlite/source/Vector3int32.cpp
index 3bd8e9f2bc2..a4867ba01c0 100644
--- a/dep/g3dlite/source/Vector3int32.cpp
+++ b/dep/g3dlite/source/Vector3int32.cpp
@@ -4,7 +4,7 @@
@author Morgan McGuire, http://graphics.cs.williams.edu
@created 2008-07-01
- @edited 2008-07-01
+ @edited 2010-10-20
*/
#include "G3D/platform.h"
@@ -15,13 +15,76 @@
#include "G3D/BinaryInput.h"
#include "G3D/BinaryOutput.h"
#include "G3D/format.h"
+#include "G3D/Vector2int32.h"
+#include "G3D/Vector2int16.h"
+#include "G3D/Any.h"
namespace G3D {
+Vector3int32 iFloor(const Vector3& v) {
+ return Vector3int32(iFloor(v.x), iFloor(v.y), iFloor(v.z));
+}
+
+Vector3int32::Vector3int32(const Any& any) {
+ *this = Vector3int32();
+ any.verifyNameBeginsWith("Vector3int32", "Point3int32");
+
+ switch (any.type()) {
+ case Any::TABLE:
+
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
+ const std::string& key = toLower(it->key);
+
+ if (key == "x") {
+ x = it->value;
+ } else if (key == "y") {
+ y = it->value;
+ } else if (key == "z") {
+ z = it->value;
+ } else {
+ any.verify(false, "Illegal key: " + it->key);
+ }
+ }
+ break;
+
+ case Any::ARRAY:
+
+ (void)any.name();
+ if (any.size() == 1) {
+ x = y = z = any[0];
+ } else {
+ any.verifySize(3);
+ x = any[0];
+ y = any[1];
+ z = any[2];
+ }
+ break;
+
+ default:
+ any.verify(false, "Bad Vector3int32 constructor");
+ }
+}
+
+
+Any Vector3int32::toAny() const {
+ Any a(Any::ARRAY, "Vector3int32");
+ a.append(x, y, z);
+ return a;
+}
+
Vector3int32::Vector3int32(const class Vector3& v) {
- x = (int32)iFloor(v.x + 0.5);
- y = (int32)iFloor(v.y + 0.5);
- z = (int32)iFloor(v.z + 0.5);
+ x = (int32)(v.x + 0.5);
+ y = (int32)(v.y + 0.5);
+ z = (int32)(v.z + 0.5);
+}
+
+Vector3int32::Vector3int32(const class Vector2int32& v, int _z) : x(v.x), y(v.y), z(_z) {}
+
+Vector3int32::Vector3int32(const class Vector2int16& v, int _z) : x(v.x), y(v.y), z(_z) {}
+
+
+Vector3int32 Vector3int32::truncate(const class Vector3& v) {
+ return Vector3int32(int32(v.x), int32(v.y), int32(v.z));
}
@@ -54,4 +117,16 @@ std::string Vector3int32::toString() const {
return G3D::format("(%d, %d, %d)", x, y, z);
}
+//----------------------------------------------------------------------------
+// 2-char swizzles
+
+Vector2int32 Vector3int32::xx() const { return Vector2int32 (x, x); }
+Vector2int32 Vector3int32::yx() const { return Vector2int32 (y, x); }
+Vector2int32 Vector3int32::zx() const { return Vector2int32 (z, x); }
+Vector2int32 Vector3int32::xy() const { return Vector2int32 (x, y); }
+Vector2int32 Vector3int32::yy() const { return Vector2int32 (y, y); }
+Vector2int32 Vector3int32::zy() const { return Vector2int32 (z, y); }
+Vector2int32 Vector3int32::xz() const { return Vector2int32 (x, z); }
+Vector2int32 Vector3int32::yz() const { return Vector2int32 (y, z); }
+Vector2int32 Vector3int32::zz() const { return Vector2int32 (z, z); }
}
diff --git a/dep/g3dlite/source/Vector4.cpp b/dep/g3dlite/source/Vector4.cpp
index b5f23d69950..0b19fa5b803 100644
--- a/dep/g3dlite/source/Vector4.cpp
+++ b/dep/g3dlite/source/Vector4.cpp
@@ -4,7 +4,7 @@
@maintainer Morgan McGuire, http://graphics.cs.williams.edu
@created 2001-07-09
- @edited 2010-07-05
+ @edited 2010-11-05
*/
#include <stdlib.h>
@@ -21,6 +21,12 @@
namespace G3D {
+Vector4& Vector4::operator=(const Any& a) {
+ *this = Vector4(a);
+ return *this;
+}
+
+
Vector4::Vector4(const Any& any) {
any.verifyName("Vector4");
any.verifyType(Any::TABLE, Any::ARRAY);
@@ -40,7 +46,8 @@ Vector4::Vector4(const Any& any) {
}
}
-Vector4::operator Any() const {
+
+Any Vector4::toAny() const {
Any any(Any::ARRAY, "Vector4");
any.append(x, y, z, w);
return any;
@@ -134,7 +141,7 @@ Vector4 Vector4::operator/ (float fScalar) const {
Vector4 kQuot;
if ( fScalar != 0.0 ) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
kQuot.x = fInvScalar * x;
kQuot.y = fInvScalar * y;
kQuot.z = fInvScalar * z;
@@ -148,13 +155,13 @@ Vector4 Vector4::operator/ (float fScalar) const {
//----------------------------------------------------------------------------
Vector4& Vector4::operator/= (float fScalar) {
if (fScalar != 0.0f) {
- float fInvScalar = 1.0f / fScalar;
+ float fInvScalar = 1.0f / fScalar;
x *= fInvScalar;
y *= fInvScalar;
z *= fInvScalar;
w *= fInvScalar;
} else {
- *this = Vector4::inf();
+ *this = Vector4::inf();
}
return *this;
@@ -511,5 +518,12 @@ Vector4 Vector4::ywww() const { return Vector4 (y, w, w, w); }
Vector4 Vector4::zwww() const { return Vector4 (z, w, w, w); }
Vector4 Vector4::wwww() const { return Vector4 (w, w, w, w); }
+void serialize(const Vector4& v, class BinaryOutput& b) {
+ v.serialize(b);
+}
+
+void deserialize(Vector4& v, class BinaryInput& b) {
+ v.deserialize(b);
+}
}; // namespace
diff --git a/dep/g3dlite/source/Welder.cpp b/dep/g3dlite/source/Welder.cpp
index 2db47722e64..55a888590c3 100644
--- a/dep/g3dlite/source/Welder.cpp
+++ b/dep/g3dlite/source/Welder.cpp
@@ -1,10 +1,10 @@
/**
- @file Welder.cpp
+ \file Welder.cpp
- @author Morgan McGuire, Kyle Whitson, Corey Taylor
+ \author Morgan McGuire, Kyle Whitson, Corey Taylor
- @created 2008-07-30
- @edited 2009-11-29
+ \created 2008-07-30
+ \edited 2011-07-04
*/
#include "G3D/platform.h"
@@ -17,9 +17,14 @@
#include "G3D/AreaMemoryManager.h"
#include "G3D/Any.h"
#include "G3D/stringutils.h"
+#include "G3D/BinaryInput.h"
+#include "G3D/BinaryOutput.h"
namespace G3D { namespace _internal{
+// Uncomment to print information that can help with performance
+// profiling.
+//#define VERBOSE
/** Used by WeldHelper2::smoothNormals. */
class VN {
@@ -98,11 +103,11 @@ private:
*/
int getIndex(const Vector3& v, const Vector3& n, const Vector2& t) {
PointHashGrid<VNTi>::SphereIterator it =
- weldGrid.beginSphereIntersection(Sphere(v, vertexWeldRadius));
+ weldGrid.begin(Sphere(v, vertexWeldRadius));
if (n.isZero()) {
// Don't bother trying to match the surface normal, since this vertex has no surface normal.
- while (it.hasMore()) {
+ while (it.isValid()) {
if ((t - it->texCoord).squaredLength() <= texCoordWeldRadius2) {
// This is the vertex
return it->index;
@@ -110,7 +115,7 @@ private:
++it;
}
} else {
- while (it.hasMore()) {
+ while (it.isValid()) {
if (((n - it->normal).squaredLength() <= normalWeldRadius2) &&
((t - it->texCoord).squaredLength() <= texCoordWeldRadius2)) {
// This is the vertex
@@ -142,12 +147,16 @@ private:
Called from process()
*/
- void updateTriLists(
- Array<Array<int>*>& indexArrayArray,
- const Array<Vector3>& vertexArray,
- const Array<Vector3>& normalArray,
- const Array<Vector2>& texCoordArray) {
-
+ void updateTriLists
+ (Array<Array<int>*>& indexArrayArray,
+ const Array<Vector3>& vertexArray,
+ const Array<Vector3>& normalArray,
+ const Array<Vector2>& texCoordArray) {
+
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::updateTriLists\n");
+# endif
+
// Compute a hash grid so that we can find neighbors quickly.
// It begins empty and is extended as the tri lists are iterated
// through.
@@ -183,13 +192,17 @@ private:
/** Expands the indexed triangle lists into a triangle list.
Called from process() */
- void unroll(
- const Array<Array<int>*>& indexArrayArray,
- const Array<Vector3>& vertexArray,
- const Array<Vector2>& texCoordArray,
- Array<Vector3>& unrolledVertexArray,
- Array<Vector2>& unrolledTexCoordArray) {
-
+ void unroll
+ (const Array<Array<int>*>& indexArrayArray,
+ const Array<Vector3>& vertexArray,
+ const Array<Vector2>& texCoordArray,
+ Array<Vector3>& unrolledVertexArray,
+ Array<Vector2>& unrolledTexCoordArray) {
+
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::unroll\n");
+# endif
+
int numTriLists = indexArrayArray.size();
for (int t = 0; t < numTriLists; ++t) {
if (indexArrayArray[t] != NULL) {
@@ -206,9 +219,12 @@ private:
/** For every three vertices, compute the face normal and store it three times.
Sliver triangles have a zero surface normal, which we will later take to
match *any* surface normal. */
- void computeFaceNormals(
- const Array<Vector3>& vertexArray,
- Array<Vector3>& faceNormalArray) {
+ void computeFaceNormals
+ (const Array<Vector3>& vertexArray,
+ Array<Vector3>& faceNormalArray) {
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::computeFaceNormals\n");
+# endif
debugAssertM(vertexArray.size() % 3 == 0, "Input is not a triangle soup");
debugAssertM(faceNormalArray.size() == 0, "Output must start empty.");
@@ -231,17 +247,19 @@ private:
Computes @a smoothNormalArray, whose elements are those of normalArray averaged
with neighbors within the angular cutoff.
*/
- void smoothNormals(
- const Array<Vector3>& vertexArray,
- const Array<Vector3>& normalArray,
- Array<Vector3>& smoothNormalArray) {
-
+ void smoothNormals
+ (const Array<Point3>& vertexArray,
+ const Array<Vector3>& normalArray,
+ Array<Vector3>& smoothNormalArray) {
if (normalSmoothingAngle <= 0) {
smoothNormalArray = normalArray;
return;
}
-
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::smoothNormals\n");
+# endif
+
// Create an area memory manager for fast deallocation
MemoryManager::Ref mm = AreaMemoryManager::create(iRound(sizeof(VN) * normalArray.size() * 1.5));
@@ -250,53 +268,110 @@ private:
debugAssert(vertexArray.size() == normalArray.size());
smoothNormalArray.resize(normalArray.size());
- // Compute a hash grid so that we can find neighbors quickly.
- PointHashGrid<VN> grid(vertexWeldRadius, mm);
- for (int v = 0; v < normalArray.size(); ++v) {
- grid.insert(VN(vertexArray[v], normalArray[v]));
- }
+ if (vertexWeldRadius == 0) {
+ // Look for vertices with the exactly identical normal only
+# ifdef VERBOSE
+ debugPrintf("Taking fast path\n");
+# endif
+
+ // Maximum expected faces that meet at a vertex
+ static const int k = 8;
+
+ // Maps vertices to the indices of normals at that vertex
+ Table<Point3, SmallArray<Vector3, k> > normalTable;
+ for (int v = 0; v < vertexArray.size(); ++v) {
+ bool ignore = false;
+ SmallArray<Vector3, k>& list = normalTable.getCreate(vertexArray[v], ignore);
+ list.append(normalArray[v]);
+ }
- // TODO: this step could be done on multiple threads
- for (int v = 0; v < normalArray.size(); ++v) {
- // Compute the sum of all nearby normals within the cutoff angle.
- // Search within the vertexWeldRadius, since those are the vertices
- // that will collapse to the same point.
- PointHashGrid<VN>::SphereIterator it =
- grid.beginSphereIntersection(Sphere(vertexArray[v], vertexWeldRadius));
+ for (int v = 0; v < vertexArray.size(); ++v) {
+ Vector3 sum;
- Vector3 sum;
+ const Vector3& original = normalArray[v];
- const Vector3& original = normalArray[v];
- while (it.hasMore()) {
- const Vector3& N = it->normal;
- const float cosAngle = N.dot(original);
+ const SmallArray<Vector3, k>& list = normalTable[vertexArray[v]];
- if (cosAngle > cosThresholdAngle) {
- // This normal is close enough to consider. Avoid underflow by scaling up
- sum += (N * 256.0f);
- }
- ++it;
- }
+ for (int i = 0; i < list.size(); ++i) {
+ const Vector3& N = list[i];
+ const float cosAngle = N.dot(original);
- const Vector3& average = sum.directionOrZero();
+ if (cosAngle > cosThresholdAngle) {
+ // This normal is close enough to consider. Avoid underflow by scaling up
+ sum += (N * 256.0f);
+ }
+ }
- const bool indeterminate = average.isZero();
- // Never "smooth" a normal so far that it points backwards
- const bool backFacing = original.dot(average) < 0;
+ const Vector3& average = sum.directionOrZero();
+
+ const bool indeterminate = average.isZero();
+ // Never "smooth" a normal so far that it points backwards
+ const bool backFacing = original.dot(average) < 0;
+
+ if (indeterminate || backFacing) {
+ // Revert to the face normal
+ smoothNormalArray[v] = original;
+ } else {
+ // Average available normals
+ smoothNormalArray[v] = average;
+ }
+ }
- if (indeterminate || backFacing) {
- // Revert to the face normal
- smoothNormalArray[v] = original;
- } else {
- // Average available normals
- smoothNormalArray[v] = average;
+ } else {
+ // Non-zero vertex normal welding
+# ifdef VERBOSE
+ debugPrintf("Taking slower weld path because vertexWeldRadius = %f\n",
+ vertexWeldRadius);
+# endif
+
+ // Compute a hash grid so that we can find neighbors quickly.
+ alwaysAssertM(vertexWeldRadius > 0, "Cannot smooth with zero vertex weld radius");
+ PointHashGrid<VN> grid(vertexWeldRadius, mm);
+ for (int v = 0; v < normalArray.size(); ++v) {
+ grid.insert(VN(vertexArray[v], normalArray[v]));
+ }
+
+ // OPT: this step could be done on multiple threads
+ for (int v = 0; v < normalArray.size(); ++v) {
+ // Compute the sum of all nearby normals within the cutoff angle.
+ // Search within the vertexWeldRadius, since those are the vertices
+ // that will collapse to the same point.
+ PointHashGrid<VN>::SphereIterator it =
+ grid.begin(Sphere(vertexArray[v], vertexWeldRadius));
+
+ Vector3 sum;
+
+ const Vector3& original = normalArray[v];
+ while (it.isValid()) {
+ const Vector3& N = it->normal;
+ const float cosAngle = N.dot(original);
+
+ if (cosAngle > cosThresholdAngle) {
+ // This normal is close enough to consider. Avoid underflow by scaling up
+ sum += (N * 256.0f);
+ }
+ ++it;
+ }
+
+ const Vector3& average = sum.directionOrZero();
+
+ const bool indeterminate = average.isZero();
+ // Never "smooth" a normal so far that it points backwards
+ const bool backFacing = original.dot(average) < 0;
+
+ if (indeterminate || backFacing) {
+ // Revert to the face normal
+ smoothNormalArray[v] = original;
+ } else {
+ // Average available normals
+ smoothNormalArray[v] = average;
+ }
}
}
}
public:
-
/**
Algorithm:
@@ -311,14 +386,17 @@ public:
4. Generate output indexArrayArray. While doing so, merge all vertices where
the distance between position, texCoord, and normal is within the thresholds.
*/
- void process(
- Array<Vector3>& vertexArray,
- Array<Vector2>& texCoordArray,
- Array<Vector3>& normalArray,
- Array<Array<int>*>& indexArrayArray,
- float normAngle,
- float texRadius,
- float normRadius) {
+ void process
+ ( Array<Vector3>& vertexArray,
+ Array<Vector2>& texCoordArray,
+ Array<Vector3>& normalArray,
+ Array<Array<int>*>& indexArrayArray,
+ float normAngle,
+ float texRadius,
+ float normRadius) {
+# ifdef VERBOSE
+ debugPrintf("WeldHelper::process\n");
+# endif
normalSmoothingAngle = normAngle;
normalWeldRadius2 = square(normRadius);
@@ -331,11 +409,17 @@ public:
"Input arrays are not parallel.");
}
+ // Create an area memory manager for fast deallocation
Array<Vector3> unrolledVertexArray;
Array<Vector3> unrolledFaceNormalArray;
Array<Vector3> unrolledSmoothNormalArray;
Array<Vector2> unrolledTexCoordArray;
+ unrolledVertexArray.reserve(vertexArray.size());
+ unrolledFaceNormalArray.reserve(vertexArray.size());
+ unrolledSmoothNormalArray.reserve(vertexArray.size());
+ unrolledTexCoordArray.reserve(vertexArray.size());
+
if (! hasTexCoords) {
// Generate all zero texture coordinates
texCoordArray.resize(vertexArray.size());
@@ -373,23 +457,40 @@ public:
}
WeldHelper(float vertRadius) :
- weldGrid(vertRadius, AreaMemoryManager::create()),
+ weldGrid(max(vertRadius, 0.1f), AreaMemoryManager::create()),
vertexWeldRadius(vertRadius) {
}
};
} // Internal
-void Welder::weld(
- Array<Vector3>& vertexArray,
- Array<Vector2>& texCoordArray,
- Array<Vector3>& normalArray,
- Array<Array<int>*>& indexArrayArray,
- const Welder::Settings& settings) {
- _internal::WeldHelper(settings.vertexWeldRadius).process(
- vertexArray, texCoordArray, normalArray, indexArrayArray,
- settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
+void Welder::Settings::serialize(class BinaryOutput& b) const {
+ b.writeFloat32(normalSmoothingAngle);
+ b.writeFloat32(vertexWeldRadius);
+ b.writeFloat32(textureWeldRadius);
+ b.writeFloat32(normalWeldRadius);
+}
+
+
+void Welder::Settings::deserialize(class BinaryInput& b) {
+ normalSmoothingAngle = b.readFloat32();
+ vertexWeldRadius = b.readFloat32();
+ textureWeldRadius = b.readFloat32();
+ normalWeldRadius = b.readFloat32();
+}
+
+
+void Welder::weld
+(Array<Vector3>& vertexArray,
+ Array<Vector2>& texCoordArray,
+ Array<Vector3>& normalArray,
+ Array<Array<int>*>& indexArrayArray,
+ const Welder::Settings& settings) {
+
+ _internal::WeldHelper(settings.vertexWeldRadius).process
+ (vertexArray, texCoordArray, normalArray, indexArrayArray,
+ settings.normalSmoothingAngle, settings.textureWeldRadius, settings.normalWeldRadius);
}
@@ -397,7 +498,7 @@ void Welder::weld(
Welder::Settings::Settings(const Any& any) {
*this = Settings();
any.verifyName("Welder::Settings");
- for (Any::AnyTable::Iterator it = any.table().begin(); it.hasMore(); ++it) {
+ for (Any::AnyTable::Iterator it = any.table().begin(); it.isValid(); ++it) {
const std::string& key = toLower(it->key);
if (key == "normalsmoothingangle") {
normalSmoothingAngle = it->value;
@@ -413,12 +514,13 @@ Welder::Settings::Settings(const Any& any) {
}
}
-Welder::Settings::operator Any() const {
+
+Any Welder::Settings::toAny() const {
Any a(Any::TABLE, "Welder::Settings");
- a.set("normalSmoothingAngle", normalSmoothingAngle);
- a.set("vertexWeldRadius", vertexWeldRadius);
- a.set("textureWeldRadius", textureWeldRadius);
- a.set("normalWeldRadius", normalWeldRadius);
+ a["normalSmoothingAngle"] = normalSmoothingAngle;
+ a["vertexWeldRadius"] = vertexWeldRadius;
+ a["textureWeldRadius"] = textureWeldRadius;
+ a["normalWeldRadius"] = normalWeldRadius;
return a;
}
diff --git a/dep/g3dlite/source/WinMain.cpp b/dep/g3dlite/source/WinMain.cpp
index 3cee71084e4..197530060f5 100644
--- a/dep/g3dlite/source/WinMain.cpp
+++ b/dep/g3dlite/source/WinMain.cpp
@@ -6,7 +6,7 @@
#include "G3D/platform.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <stdio.h>
#include <stdlib.h>
diff --git a/dep/g3dlite/source/XML.cpp b/dep/g3dlite/source/XML.cpp
index 51f1a549ba0..f347548b2db 100644
--- a/dep/g3dlite/source/XML.cpp
+++ b/dep/g3dlite/source/XML.cpp
@@ -7,7 +7,7 @@
\created 2010-02-11
\edited 2010-02-24
- Copyright 2000-2010, Morgan McGuire.
+ Copyright 2000-2012, Morgan McGuire.
All rights reserved.
*/
@@ -68,7 +68,7 @@ void XML::serialize(TextOutput& t) const {
t.writeSymbol(m_value);
} else {
t.printf("<%s", m_name.c_str());
- for (AttributeTable::Iterator it = m_attribute.begin(); it.hasMore(); ++it) {
+ for (AttributeTable::Iterator it = m_attribute.begin(); it.isValid(); ++it) {
t.printf(" %s=\"%s\"", it->key.c_str(), it->value.m_value.c_str());
}
t.printf(">");
diff --git a/dep/g3dlite/source/constants.cpp b/dep/g3dlite/source/constants.cpp
index 9ee3eb8736b..53a33faa8ec 100644
--- a/dep/g3dlite/source/constants.cpp
+++ b/dep/g3dlite/source/constants.cpp
@@ -11,6 +11,34 @@
namespace G3D {
+ const char* PrimitiveType::toString(int i, Value& v) {
+ static const char* str[] = {"POINTS", "LINES", "LINE_STRIP", "TRIANGLES", "TRIANGLE_FAN", "QUADS", "QUAD_STRIP", NULL};
+ static const Value val[] = {POINTS, LINES, LINE_STRIP, TRIANGLES, TRIANGLE_FAN, QUADS, QUAD_STRIP};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
+ const char* RefractionQuality::toString(int i, Value& v) {
+ static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_FLAT", "DYNAMIC_FLAT_MULTILAYER", "DYNAMIC_ENV", "BEST", NULL};
+ static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_FLAT, DYNAMIC_FLAT_MULTILAYER, DYNAMIC_ENV, BEST};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
+
+ const char* MirrorQuality::toString(int i, Value& v) {
+ static const char* str[] = {"NONE", "STATIC_ENV", "DYNAMIC_PLANAR", "DYNAMIC_ENV", "BEST", NULL};
+ static const Value val[] = {NONE, STATIC_ENV, DYNAMIC_PLANAR, DYNAMIC_ENV, BEST};
+ const char* s = str[i];
+ if (s) {
+ v = val[i];
+ }
+ return s;
+ }
} // G3D
diff --git a/dep/g3dlite/source/debugAssert.cpp b/dep/g3dlite/source/debugAssert.cpp
index 41aad02c640..92ce2376490 100644
--- a/dep/g3dlite/source/debugAssert.cpp
+++ b/dep/g3dlite/source/debugAssert.cpp
@@ -11,7 +11,7 @@
#include "G3D/debugAssert.h"
#include "G3D/platform.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <tchar.h>
#endif
#include "G3D/format.h"
@@ -44,7 +44,7 @@ AssertionHook _failureHook = _handleErrorCheck_;
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
static void postToClipboard(const char *text) {
if (OpenClipboard(NULL)) {
HGLOBAL hMem = GlobalAlloc(GHND | GMEM_DDESHARE, strlen(text) + 1);
@@ -77,7 +77,7 @@ static void createErrorMessage(
std::string le = "";
const char* newline = "\n";
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
newline = "\r\n";
// The last error value. (Which is preserved across the call).
@@ -106,9 +106,9 @@ static void createErrorMessage(
realLastErr = _T("Last error code does not exist.");
}
- if (lastErr != 0) {
- le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
- }
+ if (lastErr != 0) {
+ le = G3D::format("Last Error (0x%08X): %s\r\n\r\n", lastErr, (LPCSTR)realLastErr);
+ }
// Get rid of the allocated memory from FormatMessage.
if (NULL != formatMsg) {
@@ -142,7 +142,7 @@ bool _handleDebugAssert_(
std::string dialogText = "";
createErrorMessage(expression, message, filename, lineNumber, dialogTitle, dialogText);
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
DWORD lastErr = GetLastError();
postToClipboard(dialogText.c_str());
debugPrintf("\n%s\n", dialogText.c_str());
@@ -159,7 +159,7 @@ bool _handleDebugAssert_(
int result = G3D::prompt(dialogTitle.c_str(), dialogText.c_str(), (const char**)choices, 3, useGuiPrompt);
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
// Put the incoming last error back.
SetLastError(lastErr);
# endif
@@ -200,7 +200,7 @@ bool _handleErrorCheck_(
// Log the error
Log::common()->print(std::string("\n**************************\n\n") + dialogTitle + "\n" + dialogText);
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
DWORD lastErr = GetLastError();
(void)lastErr;
postToClipboard(dialogText.c_str());
@@ -212,7 +212,7 @@ bool _handleErrorCheck_(
const std::string& m =
std::string("An internal error has occured in this program and it will now close. "
"The specific error is below. More information has been saved in \"") +
- Log::getCommonLogFilename() + "\".\n" + dialogText;
+ Log::getCommonLogFilename() + "\".\n\n" + dialogText;
int result = G3D::prompt("Error", m.c_str(), (const char**)choices, 1, useGuiPrompt);
(void)result;
@@ -221,7 +221,7 @@ bool _handleErrorCheck_(
}
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
static HCURSOR oldCursor;
static RECT oldCursorRect;
static POINT oldCursorPos;
@@ -229,7 +229,7 @@ static int oldShowCursorCount;
#endif
void _releaseInputGrab_() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
GetCursorPos(&oldCursorPos);
@@ -275,7 +275,7 @@ void _releaseInputGrab_() {
void _restoreInputGrab_() {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
// Restore the old clipping region
ClipCursor(&oldCursorRect);
@@ -307,7 +307,7 @@ void setAssertionHook(AssertionHook hook) {
}
AssertionHook assertionHook() {
- return G3D::_internal::_debugHook;
+ return G3D::_internal::_debugHook;
}
void setFailureHook(AssertionHook hook) {
@@ -329,7 +329,7 @@ ConsolePrintHook consolePrintHook() {
std::string __cdecl debugPrint(const std::string& s) {
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
const int MAX_STRING_LEN = 1024;
// Windows can't handle really long strings sent to
diff --git a/dep/g3dlite/source/fileutils.cpp b/dep/g3dlite/source/fileutils.cpp
index 1867bf3338e..966cca7d4bf 100644
--- a/dep/g3dlite/source/fileutils.cpp
+++ b/dep/g3dlite/source/fileutils.cpp
@@ -25,7 +25,7 @@
#include "zip.h"
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
// Needed for _getcwd
#include <direct.h>
#include <io.h>
@@ -63,7 +63,7 @@ std::string resolveFilename(const std::string& filename) {
return filename;
} else {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if ((filename.size() >= 2) && (filename[1] == ':')) {
// There is a drive spec on the front.
if ((filename.size() >= 3) && ((filename[2] == '\\') ||
@@ -86,36 +86,43 @@ std::string resolveFilename(const std::string& filename) {
char buffer[1024];
// Prepend the working directory.
- _getcwd(buffer, 1024);
+ (void)_getcwd(buffer, 1024);
return format("%s/%s", buffer, filename.c_str());
}
bool zipfileExists(const std::string& filename) {
- std::string outZipfile;
- std::string outInternalFile;
+ std::string outZipfile;
+ std::string outInternalFile;
return zipfileExists(filename, outZipfile, outInternalFile);
}
-std::string readWholeFile(
- const std::string& filename) {
- _internal::currentFilesUsed.insert(filename);
+std::string readWholeFile(const std::string& filename) {
std::string s;
debugAssert(filename != "");
- debugAssertM(FileSystem::exists(filename), filename + " not found");
+ if (! FileSystem::exists(filename)) {
+ throw (filename + " not found");
+ }
+ FileSystem::markFileUsed(filename);
+ std::string zipfile;
+
+ if (! FileSystem::inZipfile(filename, zipfile)) {
+ // Not in zipfile
+ if (! FileSystem::exists(filename)) {
+ throw FileNotFound(filename, std::string("File not found in readWholeFile: ") + filename);
+ }
- if (! FileSystem::inZipfile(filename)) {
int64 length = FileSystem::size(filename);
char* buffer = (char*)System::alignedMalloc(length + 1, 16);
debugAssert(buffer);
FILE* f = FileSystem::fopen(filename.c_str(), "rb");
debugAssert(f);
- int ret = fread(buffer, 1, length, f);
- debugAssert(ret == length);(void)ret;
+ int64 ret = fread(buffer, 1, length, f);
+ debugAssert(ret == length);(void)ret;
FileSystem::fclose(f);
buffer[length] = '\0';
@@ -123,60 +130,43 @@ std::string readWholeFile(
System::alignedFree(buffer);
- } else if (zipfileExists(filename)) {
-
- void* zipBuffer;
- size_t length;
- zipRead(filename, zipBuffer, length);
-
- char* buffer = (char*)System::alignedMalloc(length + 1, 16);
- System::memcpy(buffer,zipBuffer, length + 1);
- zipClose(zipBuffer);
-
- buffer[length] = '\0';
- s = std::string(buffer);
- System::alignedFree(buffer);
- }
-
- return s;
-}
+ } else {
+ // In zipfile
+ FileSystem::markFileUsed(zipfile);
-void zipRead(const std::string& file,
- void*& data,
- size_t& length) {
- std::string zip, desiredFile;
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- if (zipfileExists(file, zip, desiredFile)) {
- struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
+ // Zipfiles require Unix-style slashes
+ std::string internalFile = FilePath::canonicalize(filename.substr(zipfile.length() + 1));
+ struct zip* z = zip_open(zipfile.c_str(), ZIP_CHECKCONS, NULL);
{
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
- zip_stat( z, desiredFile.c_str(), ZIP_FL_NOCASE, &info );
- length = info.size;
- // sets machines up to use MMX, if they want
- data = System::alignedMalloc(length, 16);
- struct zip_file *zf = zip_fopen( z, desiredFile.c_str(), ZIP_FL_NOCASE );
- {
- int test = zip_fread( zf, data, length );
- debugAssertM((size_t)test == length,
- desiredFile + " was corrupt because it unzipped to the wrong size.");
- (void)test;
+ zip_stat(z, internalFile.c_str(), ZIP_FL_NOCASE, &info);
+
+ // Add NULL termination
+ char* buffer = reinterpret_cast<char*>(System::alignedMalloc(info.size + 1, 16));
+ buffer[info.size] = '\0';
+
+ struct zip_file* zf = zip_fopen( z, internalFile.c_str(), ZIP_FL_NOCASE );
+ if (zf == NULL) {
+ throw std::string("\"") + internalFile + "\" inside \"" + zipfile + "\" could not be opened.";
+ } else {
+ const int64 bytesRead = zip_fread( zf, buffer, (info.size));
+ debugAssertM((int64)bytesRead == (int64)info.size,
+ internalFile + " was corrupt because it unzipped to the wrong size.");
+ (void)bytesRead;
+ zip_fclose( zf );
}
- zip_fclose( zf );
+ // Copy the string
+ s = buffer;
+ System::alignedFree(buffer);
}
zip_close( z );
- } else {
- data = NULL;
- }
-#else
- data = NULL;
#endif
-}
-
+ }
-void zipClose(void* data) {
- System::alignedFree(data);
+ return s;
}
@@ -186,25 +176,25 @@ int64 fileLength(const std::string& filename) {
if (result == -1) {
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
- std::string zip, contents;
- if(zipfileExists(filename, zip, contents)){
- int64 requiredMem;
+ std::string zip, contents;
+ if(zipfileExists(filename, zip, contents)){
+ int64 requiredMem;
struct zip *z = zip_open( zip.c_str(), ZIP_CHECKCONS, NULL );
debugAssertM(z != NULL, zip + ": zip open failed.");
- {
+ {
struct zip_stat info;
zip_stat_init( &info ); // TODO: Docs unclear if zip_stat_init is required.
int success = zip_stat( z, contents.c_str(), ZIP_FL_NOCASE, &info );
- (void)success;
+ (void)success;
debugAssertM(success == 0, zip + ": " + contents + ": zip stat failed.");
requiredMem = info.size;
- }
+ }
zip_close( z );
- return requiredMem;
- } else {
+ return requiredMem;
+ } else {
return -1;
- }
+ }
#else
return -1;
#endif
@@ -251,9 +241,9 @@ void writeWholeFile(
void createDirectory(
const std::string& dir) {
- if (dir == "") {
- return;
- }
+ if (dir == "") {
+ return;
+ }
std::string d;
@@ -292,11 +282,11 @@ void createDirectory(
if (! FileSystem::exists(p)) {
// Windows only requires one argument to mkdir,
// where as unix also requires the permissions.
-# ifndef G3D_WIN32
+# ifndef G3D_WINDOWS
mkdir(p.c_str(), 0777);
-# else
+# else
_mkdir(p.c_str());
-# endif
+# endif
}
}
}
@@ -308,39 +298,40 @@ void createDirectory(
/* Helper methods for zipfileExists()*/
// Given a string (the drive) and an array (the path), computes the directory
static void _zip_resolveDirectory(std::string& completeDir, const std::string& drive, const Array<std::string>& path, const int length){
- completeDir = drive;
- int tempLength;
- // if the given length is longer than the array, we correct it
- if(length > path.length()){
- tempLength = path.length();
- } else{
- tempLength = length;
- }
-
- for(int t = 0; t < tempLength; ++t){
- if(t > 0){
- completeDir += "/";
- }
- completeDir += path[t];
- }
+ completeDir = drive;
+ int tempLength;
+ // if the given length is longer than the array, we correct it
+ if(length > path.length()){
+ tempLength = path.length();
+ } else{
+ tempLength = length;
+ }
+
+ for(int t = 0; t < tempLength; ++t){
+ if(t > 0){
+ completeDir += "/";
+ }
+ completeDir += path[t];
+ }
}
-// assumes that zipDir references a .zip file
+/** assumes that zipDir references a .zip file */
static bool _zip_zipContains(const std::string& zipDir, const std::string& desiredFile){
struct zip *z = zip_open( zipDir.c_str(), ZIP_CHECKCONS, NULL );
- //the last parameter, an int, determines case sensitivity:
- //1 is sensitive, 2 is not, 0 is default
+ //the last parameter, an int, determines case sensitivity:
+ //1 is sensitive, 2 is not, 0 is default
int test = zip_name_locate( z, desiredFile.c_str(), ZIP_FL_NOCASE );
zip_close( z );
- if(test == -1){
- return false;
- }
- return true;
+ if(test == -1){
+ return false;
+ }
+ return true;
}
#endif
-// If no zipfile exists, outZipfile and outInternalFile are unchanged
+
+/** If no zipfile exists, outZipfile and outInternalFile are unchanged */
bool zipfileExists(const std::string& filename, std::string& outZipfile,
std::string& outInternalFile){
#if _HAVE_ZIP /* G3DFIX: Use ZIP-library only if defined */
@@ -355,7 +346,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
infile = base + ext;
}
- // Remove "." from path
+ // Remove all standalone single dots (".") from path
for (int i = 0; i < path.length(); ++i) {
if (path[i] == ".") {
path.remove(i);
@@ -363,7 +354,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
}
}
- // Remove ".." from path
+ // Remove non-leading ".." from path
for (int i = 1; i < path.length(); ++i) {
if ((path[i] == "..") && (i > 0) && (path[i - 1] != "..")) {
// Remove both i and i - 1
@@ -409,7 +400,7 @@ bool zipfileExists(const std::string& filename, std::string& outZipfile,
// not a valid directory structure ever,
// obviously no .zip was found within the path
return false;
-}
+}
///////////////////////////////////////////////////////////////////////////////
@@ -418,11 +409,14 @@ std::string generateFilenameBase(const std::string& prefix, const std::string& s
// Note "template" is a reserved word in C++
std::string templat = prefix + System::currentDateString() + "_";
- FileSystem::getFiles(templat + "*", exist);
+ FileSystem::getFiles(templat + "*", exist, true);
// Remove extensions
for (int i = 0; i < exist.size(); ++i) {
- exist[i] = filenameBase(exist[i]);
+ const std::string ext = FilePath::ext(exist[i]);
+ if (ext.length() > 0) {
+ exist[i] = exist[i].substr(0, exist[i].length() - ext.length() - 1);
+ }
}
int num = 0;
@@ -442,7 +436,7 @@ void copyFile(
const std::string& source,
const std::string& dest) {
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
CopyFileA(source.c_str(), dest.c_str(), FALSE);
#else
// TODO: don't use BinaryInput and BinaryOutput
@@ -512,7 +506,7 @@ void parseFilename(
if (i != std::string::npos) {
// Make sure it is after the last slash!
- size_t j = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t j = maxNotNPOS(f.rfind('/'), f.rfind('\\'));
if ((j == std::string::npos) || (i > j)) {
ext = f.substr(i + 1, f.size() - i - 1);
f = f.substr(0, i);
@@ -523,7 +517,7 @@ void parseFilename(
// Pull the basename off
{
// Find the last slash
- size_t i = iMax(f.rfind('/'), f.rfind('\\'));
+ size_t i = maxNotNPOS(f.rfind('/'), f.rfind('\\'));
if (i == std::string::npos) {
@@ -556,7 +550,7 @@ void parseFilename(
j = f.size();
}
- cur = iMin(i, j);
+ cur = min(i, j);
if (cur == std::string::npos) {
cur = f.size();
@@ -576,9 +570,9 @@ void parseFilename(
@param includePath If true, the names include paths
*/
static void getFileOrDirListNormal
-(const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
+(const std::string& filespec,
+ Array<std::string>& files,
+ bool wantFiles,
bool includePath) {
bool test = wantFiles ? true : false;
@@ -614,11 +608,11 @@ static void getFileOrDirListNormal
path = path.substr(0, path.size() - 1);
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
{
struct _finddata_t fileinfo;
- long handle = _findfirst(filespec.c_str(), &fileinfo);
+ long handle = (long)_findfirst(filespec.c_str(), &fileinfo);
int result = handle;
while (result != -1) {
@@ -695,10 +689,10 @@ static void getFileOrDirListNormal
*/
static void _zip_addEntry(const std::string& path,
const std::string& prefix,
- const std::string& file,
- Set<std::string>& files,
- bool wantFiles,
- bool includePath) {
+ const std::string& file,
+ Set<std::string>& files,
+ bool wantFiles,
+ bool includePath) {
// Make certain we are within the desired parent folder (prefix)
if (beginsWith(file, prefix)) {
@@ -740,6 +734,7 @@ static void _zip_addEntry(const std::string& path,
}
#endif
+
static void getFileOrDirListZip(const std::string& path,
const std::string& prefix,
Array<std::string>& files,
@@ -766,13 +761,13 @@ static void getFileOrDirListZip(const std::string& path,
static void determineFileOrDirList(
- const std::string& filespec,
- Array<std::string>& files,
- bool wantFiles,
- bool includePath) {
+ const std::string& filespec,
+ Array<std::string>& files,
+ bool wantFiles,
+ bool includePath) {
- // if it is a .zip, prefix will specify the folder within
- // whose contents we want to see
+ // if it is a .zip, prefix will specify the folder within
+ // whose contents we want to see
std::string prefix = "";
std::string path = filenamePath(filespec);
@@ -800,39 +795,39 @@ static void determineFileOrDirList(
}
-void getFiles(const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
+void getFiles(const std::string& filespec,
+ Array<std::string>& files,
+ bool includePath) {
determineFileOrDirList(filespec, files, true, includePath);
}
void getDirs(
- const std::string& filespec,
- Array<std::string>& files,
- bool includePath) {
+ const std::string& filespec,
+ Array<std::string>& files,
+ bool includePath) {
- determineFileOrDirList(filespec, files, false, includePath);
+ determineFileOrDirList(filespec, files, false, includePath);
}
std::string filenameBaseExt(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
+ size_t i = filename.rfind("/");
+ size_t j = filename.rfind("\\");
- if ((j > i) && (j >= 0)) {
+ if ((j > i) && (j != std::string::npos)) {
i = j;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return filename;
} else {
return filename.substr(i + 1, filename.length() - i);
@@ -852,8 +847,8 @@ std::string filenameBase(const std::string& s) {
std::string filenameExt(const std::string& filename) {
- int i = filename.rfind(".");
- if (i >= 0) {
+ size_t i = filename.rfind(".");
+ if (i != std::string::npos) {
return filename.substr(i + 1, filename.length() - i);
} else {
return "";
@@ -862,21 +857,21 @@ std::string filenameExt(const std::string& filename) {
std::string filenamePath(const std::string& filename) {
- int i = filename.rfind("/");
- int j = filename.rfind("\\");
+ size_t i = filename.rfind("/");
+ size_t j = filename.rfind("\\");
- if ((j > i) && (j >= 0)) {
+ if ((j > i) && (j != std::string::npos)) {
i = j;
}
-# ifdef G3D_WIN32
+# ifdef G3D_WINDOWS
j = filename.rfind(":");
- if ((i == -1) && (j >= 0)) {
+ if ((i == std::string::npos) && (j != std::string::npos)) {
i = j;
}
# endif
- if (i == -1) {
+ if (i == std::string::npos) {
return "";
} else {
return filename.substr(0, i+1);
@@ -886,23 +881,23 @@ std::string filenamePath(const std::string& filename) {
bool isZipfile(const std::string& filename) {
- FILE* f = fopen(filename.c_str(), "r");
- if (f == NULL) {
- return false;
- }
- uint8 header[4];
- fread(header, 4, 1, f);
-
- const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
- for (int i = 0; i < 4; ++i) {
- if (header[i] != zipHeader[i]) {
- fclose(f);
- return false;
- }
- }
-
- fclose(f);
- return true;
+ FILE* f = fopen(filename.c_str(), "r");
+ if (f == NULL) {
+ return false;
+ }
+ uint8 header[4];
+ (void)fread(header, 4, 1, f);
+
+ const uint8 zipHeader[4] = {0x50, 0x4b, 0x03, 0x04};
+ for (int i = 0; i < 4; ++i) {
+ if (header[i] != zipHeader[i]) {
+ fclose(f);
+ return false;
+ }
+ }
+
+ fclose(f);
+ return true;
}
@@ -928,15 +923,8 @@ bool fileIsNewer(const std::string& src, const std::string& dst) {
return sexists && ((! dexists) || (sts.st_mtime > dts.st_mtime));
}
-
-Array<std::string> filesUsed() {
- Array<std::string> f;
- _internal::currentFilesUsed.getMembers(f);
- return f;
-}
-
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
#undef _stat
#endif
diff --git a/dep/g3dlite/source/format.cpp b/dep/g3dlite/source/format.cpp
index d9d1b516393..b77b30c73bd 100644
--- a/dep/g3dlite/source/format.cpp
+++ b/dep/g3dlite/source/format.cpp
@@ -43,7 +43,7 @@ std::string vformat(const char *fmt, va_list argPtr) {
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
- char stackBuffer[bufSize];
+ char stackBuffer[bufSize];
// MSVC does not support va_copy
int actualSize = _vscprintf(fmt, argPtr) + 1;
@@ -83,12 +83,12 @@ std::string vformat(const char *fmt, va_list argPtr) {
// allocate it on the stack because this saves
// the malloc/free time.
const int bufSize = 161;
- char stackBuffer[bufSize];
+ char stackBuffer[bufSize];
- // MSVC6 doesn't support va_copy, however it also seems to compile
- // correctly if we just pass our argument list along. Note that
- // this whole code block is only compiled if we're on MSVC6 anyway
- int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
+ // MSVC6 doesn't support va_copy, however it also seems to compile
+ // correctly if we just pass our argument list along. Note that
+ // this whole code block is only compiled if we're on MSVC6 anyway
+ int actualWritten = _vsnprintf(stackBuffer, bufSize, fmt, argPtr);
// Not a big enough buffer, bufSize characters written
if (actualWritten == -1) {
diff --git a/dep/g3dlite/source/g3dfnmatch.cpp b/dep/g3dlite/source/g3dfnmatch.cpp
index 2d24c4126e6..1902d71fc92 100644
--- a/dep/g3dlite/source/g3dfnmatch.cpp
+++ b/dep/g3dlite/source/g3dfnmatch.cpp
@@ -1,10 +1,10 @@
/* $Id: g3dfnmatch.cpp,v 1.3 2010/03/15 05:01:23 morgan3d Exp $ */
-/* $OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $ */
+/* $OpenBSD: fnmatch.c,v 1.7 2000/03/23 19:13:51 millert Exp $ */
/*
* Copyright (c) 1989, 1993, 1994
- * The Regents of the University of California. All rights reserved.
+ * The Regents of the University of California. All rights reserved.
*
* This code is derived from software contributed to Berkeley by
* Guido van Rossum.
@@ -19,8 +19,8 @@
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
* 4. Neither the name of the University nor the names of its contributors
* may be used to endorse or promote products derived from this software
* without specific prior written permission.
@@ -39,7 +39,7 @@
*/
#include "G3D/g3dfnmatch.h"
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
#include <ctype.h>
#include <string.h>
@@ -47,166 +47,166 @@
namespace G3D {
-#define EOS '\0'
+#define EOS '\0'
-#define RANGE_MATCH 1
-#define RANGE_NOMATCH 0
-#define RANGE_ERROR (-1)
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
static int rangematch(const char *, char, int, char **);
int
g3dfnmatch(const char *pattern, const char *string, int flags)
{
- const char *stringstart;
- char *newp;
- char c, test;
-
- for (stringstart = string;;)
- switch (c = *pattern++) {
- case EOS:
- if ((flags & FNM_LEADING_DIR) && *string == '/')
- return (0);
- return (*string == EOS ? 0 : FNM_NOMATCH);
- case '?':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
- ++string;
- break;
- case '*':
- c = *pattern;
- /* Collapse multiple stars. */
- while (c == '*')
- c = *++pattern;
-
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- /* Optimize for pattern with * at end or before /. */
- if (c == EOS) {
- if (flags & FNM_PATHNAME)
- return ((flags & FNM_LEADING_DIR) ||
- strchr(string, '/') == NULL ?
- 0 : FNM_NOMATCH);
- else
- return (0);
- } else if (c == '/' && (flags & FNM_PATHNAME)) {
- if ((string = strchr(string, '/')) == NULL)
- return (FNM_NOMATCH);
- break;
- }
-
- /* General case, use recursion. */
- while ((test = *string) != EOS) {
- if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD))
- return (0);
- if (test == '/' && (flags & FNM_PATHNAME))
- break;
- ++string;
- }
- return (FNM_NOMATCH);
- case '[':
- if (*string == EOS)
- return (FNM_NOMATCH);
- if (*string == '/' && (flags & FNM_PATHNAME))
- return (FNM_NOMATCH);
- if (*string == '.' && (flags & FNM_PERIOD) &&
- (string == stringstart ||
- ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
- return (FNM_NOMATCH);
-
- switch (rangematch(pattern, *string, flags, &newp)) {
- case RANGE_ERROR:
- /* not a good range, treat as normal text */
- goto normal;
- case RANGE_MATCH:
- pattern = newp;
- break;
- case RANGE_NOMATCH:
- return (FNM_NOMATCH);
- }
- ++string;
- break;
- case '\\':
- if (!(flags & FNM_NOESCAPE)) {
- if ((c = *pattern++) == EOS) {
- c = '\\';
- --pattern;
- }
- }
- /* FALLTHROUGH */
- default:
- normal:
- if (c != *string && !((flags & FNM_CASEFOLD) &&
- (tolower((unsigned char)c) ==
- tolower((unsigned char)*string))))
- return (FNM_NOMATCH);
- ++string;
- break;
- }
- /* NOTREACHED */
+ const char *stringstart;
+ char *newp;
+ char c, test;
+
+ for (stringstart = string;;)
+ switch (c = *pattern++) {
+ case EOS:
+ if ((flags & FNM_LEADING_DIR) && *string == '/')
+ return (0);
+ return (*string == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS) {
+ if (flags & FNM_PATHNAME)
+ return ((flags & FNM_LEADING_DIR) ||
+ strchr(string, '/') == NULL ?
+ 0 : FNM_NOMATCH);
+ else
+ return (0);
+ } else if (c == '/' && (flags & FNM_PATHNAME)) {
+ if ((string = strchr(string, '/')) == NULL)
+ return (FNM_NOMATCH);
+ break;
+ }
+
+ /* General case, use recursion. */
+ while ((test = *string) != EOS) {
+ if (!g3dfnmatch(pattern, string, flags & ~FNM_PERIOD))
+ return (0);
+ if (test == '/' && (flags & FNM_PATHNAME))
+ break;
+ ++string;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (*string == EOS)
+ return (FNM_NOMATCH);
+ if (*string == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (*string == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ switch (rangematch(pattern, *string, flags, &newp)) {
+ case RANGE_ERROR:
+ /* not a good range, treat as normal text */
+ goto normal;
+ case RANGE_MATCH:
+ pattern = newp;
+ break;
+ case RANGE_NOMATCH:
+ return (FNM_NOMATCH);
+ }
+ ++string;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ if ((c = *pattern++) == EOS) {
+ c = '\\';
+ --pattern;
+ }
+ }
+ /* FALLTHROUGH */
+ default:
+ normal:
+ if (c != *string && !((flags & FNM_CASEFOLD) &&
+ (tolower((unsigned char)c) ==
+ tolower((unsigned char)*string))))
+ return (FNM_NOMATCH);
+ ++string;
+ break;
+ }
+ /* NOTREACHED */
}
static int
rangematch(const char *pattern, char test, int flags, char **newp)
{
- int negate, ok;
- char c, c2;
-
- /*
- * A bracket expression starting with an unquoted circumflex
- * character produces unspecified results (IEEE 1003.2-1992,
- * 3.13.2). This implementation treats it like '!', for
- * consistency with the regular expression syntax.
- * J.T. Conklin (conklin@ngai.kaleida.com)
- */
- if ((negate = (*pattern == '!' || *pattern == '^')))
- ++pattern;
-
- if (flags & FNM_CASEFOLD)
- test = tolower((unsigned char)test);
-
- /*
- * A right bracket shall lose its special meaning and represent
- * itself in a bracket expression if it occurs first in the list.
- * -- POSIX.2 2.8.3.2
- */
- ok = 0;
- c = *pattern++;
- do {
- if (c == '\\' && !(flags & FNM_NOESCAPE))
- c = *pattern++;
- if (c == EOS)
- return (RANGE_ERROR);
- if (c == '/' && (flags & FNM_PATHNAME))
- return (RANGE_NOMATCH);
- if ((flags & FNM_CASEFOLD))
- c = tolower((unsigned char)c);
- if (*pattern == '-'
- && (c2 = *(pattern+1)) != EOS && c2 != ']') {
- pattern += 2;
- if (c2 == '\\' && !(flags & FNM_NOESCAPE))
- c2 = *pattern++;
- if (c2 == EOS)
- return (RANGE_ERROR);
- if (flags & FNM_CASEFOLD)
- c2 = tolower((unsigned char)c2);
- if (c <= test && test <= c2)
- ok = 1;
- } else if (c == test)
- ok = 1;
- } while ((c = *pattern++) != ']');
-
- *newp = (char *)pattern;
- return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
+ int negate, ok;
+ char c, c2;
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if ((negate = (*pattern == '!' || *pattern == '^')))
+ ++pattern;
+
+ if (flags & FNM_CASEFOLD)
+ test = tolower((unsigned char)test);
+
+ /*
+ * A right bracket shall lose its special meaning and represent
+ * itself in a bracket expression if it occurs first in the list.
+ * -- POSIX.2 2.8.3.2
+ */
+ ok = 0;
+ c = *pattern++;
+ do {
+ if (c == '\\' && !(flags & FNM_NOESCAPE))
+ c = *pattern++;
+ if (c == EOS)
+ return (RANGE_ERROR);
+ if (c == '/' && (flags & FNM_PATHNAME))
+ return (RANGE_NOMATCH);
+ if ((flags & FNM_CASEFOLD))
+ c = tolower((unsigned char)c);
+ if (*pattern == '-'
+ && (c2 = *(pattern+1)) != EOS && c2 != ']') {
+ pattern += 2;
+ if (c2 == '\\' && !(flags & FNM_NOESCAPE))
+ c2 = *pattern++;
+ if (c2 == EOS)
+ return (RANGE_ERROR);
+ if (flags & FNM_CASEFOLD)
+ c2 = tolower((unsigned char)c2);
+ if (c <= test && test <= c2)
+ ok = 1;
+ } else if (c == test)
+ ok = 1;
+ } while ((c = *pattern++) != ']');
+
+ *newp = (char *)pattern;
+ return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
}
}
diff --git a/dep/g3dlite/source/g3dmath.cpp b/dep/g3dlite/source/g3dmath.cpp
index e846f8c6080..a6ce20d872f 100644
--- a/dep/g3dlite/source/g3dmath.cpp
+++ b/dep/g3dlite/source/g3dmath.cpp
@@ -10,6 +10,7 @@
#include "G3D/g3dmath.h"
#include <cstdlib>
#include <cstring>
+#include "G3D/BIN.h"
namespace G3D {
@@ -40,14 +41,27 @@ double inf() {
return std::numeric_limits<double>::infinity();
}
+// --fast-math breaks other methods of testing for NaN on g++ 4.x,
+// including isnan(x) and !(x == x)
+
bool isNaN(float x) {
- static const float n = fnan();
- return memcmp(&x, &n, sizeof(float)) == 0;
+ // Wipe out the sign bit
+ const uint32 y = *(uint32*)(&x) & BIN32(01111111,11111111,11111111,11111111);
+
+ // If the remaining number has all of the exponent bits set and atleast one
+ // fraction bit set, then it is NaN
+ return (y > 0x7F800000);
}
bool isNaN(double x) {
- static const double n = nan();
- return memcmp(&x, &n, sizeof(double)) == 0;
+ // Wipe out the sign bit
+ const uint64 y = *(uint64*)(&x) &
+ ((uint64(BIN32(01111111,11111111,11111111,11111111)) << 32) +
+ 0xFFFFFFFF);
+
+ // If the remaining number has all of the exponent bits set and atleast one
+ // fraction bit set, then it is NaN
+ return (y > (uint64(BIN32(01111111,11110000,00000000,00000000)) << 32));
}
@@ -75,7 +89,7 @@ int highestBit(uint32 x) {
// Binary search.
int base = 0;
- if (x & 0xffff0000) {
+ if (x & 0xffff0000) {
base = 16;
x >>= 16;
}
diff --git a/dep/g3dlite/source/license.cpp b/dep/g3dlite/source/license.cpp
index 5049184cf9b..e2b9f2583d5 100644
--- a/dep/g3dlite/source/license.cpp
+++ b/dep/g3dlite/source/license.cpp
@@ -24,7 +24,7 @@ std::string license() {
"%s"
"This program uses the G3D Library (http://g3d.sf.net), which\n"
"is licensed under the \"Modified BSD\" Open Source license. The G3D library\n"
-"source code is Copyright © 2000-2010, Morgan McGuire, All rights reserved.\n"
+"source code is Copyright © 2000-2011, Morgan McGuire, All rights reserved.\n"
"This program uses The OpenGL Extension Wrangler Library, which \n"
"is licensed under the \"Modified BSD\" Open Source license. \n"
"The OpenGL Extension Wrangler Library source code is\n"
@@ -59,7 +59,7 @@ std::string license() {
"\n\n"
"G3D VERSION %d\n",
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
"" // Win32 doesn't use SDL
#else
"This software uses the Simple DirectMedia Layer library (\"SDL\",\n"
diff --git a/dep/g3dlite/source/prompt.cpp b/dep/g3dlite/source/prompt.cpp
index d2c6f098033..ee520d85db7 100644
--- a/dep/g3dlite/source/prompt.cpp
+++ b/dep/g3dlite/source/prompt.cpp
@@ -14,7 +14,7 @@
#include <stdio.h>
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
# include <sstream>
# include <conio.h>
#else
@@ -29,7 +29,7 @@
#endif
*/
-# include <Carbon/Carbon.h>
+# include "G3D/prompt_cocoa.h"
/*
#ifdef G3D_64BIT
@@ -43,7 +43,7 @@
namespace G3D {
#if 0 /* G3DFIX: exclude GUI prompt code */
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
namespace _internal {
/**
@@ -360,8 +360,8 @@ static int guiPrompt(
const char** choice,
int numChoices) {
- int width = 280;
- int height = 128;
+ int width = 340;
+ int height = 220;
const int buttonSpacing = 2;
const int buttonWidth =
@@ -381,7 +381,7 @@ static int guiPrompt(
2, 2, width - 4, height - buttonHeight - 7, IDC_MESSAGE);
int i;
- for (i = 0; i < numChoices; i++) {
+ for (i = 0; i < numChoices; ++i) {
int x = buttonSpacing + i * (buttonWidth + buttonSpacing);
int y = height - buttonHeight - buttonSpacing;
@@ -429,7 +429,7 @@ static int guiPrompt(
params.title = windowTitle;
HMODULE module = GetModuleHandle(0);
- int ret = DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)&params);
+ int ret = (int)DialogBoxIndirectParam(module, dialogTemplate, NULL, (DLGPROC) PromptDlgProc, (DWORD)&params);
free(newStr);
@@ -500,7 +500,7 @@ static int textPrompt(
while ((c < 0) || (c >= numChoices)) {
printf("\n");
- for (int i = 0; i < numChoices; i++) {
+ for (int i = 0; i < numChoices; ++i) {
if (numChoices <= 3) {
printf(" (%d) %s ", i, choice[i]);
} else {
@@ -536,167 +536,20 @@ static int textPrompt(
}
#if 0 /* G3DFIX: exclude GUI prompt code */
-
#ifdef G3D_OSX
-// See http://developer.apple.com/documentation/Carbon/Reference/Carbon_Event_Manager_Ref/index.html
-
-#define CARBON_COMMANDID_START 128
-#define CARBON_BUTTON_SPACING 12
-#define CARBON_BUTTON_HEIGHT 20
-#define CARBON_BUTTON_MINWIDTH 69
-#define CARBON_WINDOW_PADDING 20
-
-struct CallbackData {
- WindowRef refWindow;
-
- /** Index of this particular button */
- int myIndex;
-
- /** Buttons store their index into here when pressed. */
- int* whichButton;
-};
-
-/**
- Assumes that userData is a pointer to a carbon_evt_data_t.
-
- */
-static pascal OSStatus DoCommandEvent(EventHandlerCallRef handlerRef, EventRef event, void* userData) {
- // See http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/index.html
-
- CallbackData& callbackData = *(CallbackData*)userData;
-
-# pragma unused(handlerRef)
-
- callbackData.whichButton[0] = callbackData.myIndex;
-
- // If we get here we can close the window
- ::QuitAppModalLoopForWindow(callbackData.refWindow);
-
- // Return noErr to indicate that we handled the event
- return noErr;
-}
-
static int guiPrompt
(const char* windowTitle,
const char* prompt,
const char** choice,
int numChoices) {
-
- WindowRef window;
-
- int iNumButtonRows = 0;
- int iButtonWidth = -1;
- OSStatus err = noErr;
-
- // Determine number of rows of buttons
- while (iButtonWidth < CARBON_BUTTON_MINWIDTH) {
- ++iNumButtonRows;
- iButtonWidth =
- (550 - (CARBON_WINDOW_PADDING*2 +
- (CARBON_BUTTON_SPACING*numChoices))) /
- (numChoices/iNumButtonRows);
- }
-
- // Window Variables
- Rect rectWin = {0, 0, 200 + ((iNumButtonRows-1) * (CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)), 550}; // top, left, bottom, right
- CFStringRef szWindowTitle = CFStringCreateWithCString(kCFAllocatorDefault, windowTitle, kCFStringEncodingUTF8);
-
- window = NULL;
-
- err = CreateNewWindow(kMovableAlertWindowClass, kWindowStandardHandlerAttribute|kWindowCompositingAttribute, &rectWin, &window);
- err = SetWindowTitleWithCFString(window, szWindowTitle);
- err = SetThemeWindowBackground(window, kThemeBrushAlertBackgroundActive, false);
- assert(err == noErr);
-
- // Event Handler Variables
- EventTypeSpec buttonSpec[] = {{ kEventClassControl, kEventControlHit }, { kEventClassCommand, kEventCommandProcess }};
- EventHandlerUPP buttonHandler = NewEventHandlerUPP(DoCommandEvent);
-
- // Static Text Variables
- Rect rectStatic = {20, 20, 152, 530};
- CFStringRef szStaticText = CFStringCreateWithCString(kCFAllocatorDefault, prompt, kCFStringEncodingUTF8);
- ControlRef refStaticText = NULL;
- err = CreateStaticTextControl(window, &rectStatic, szStaticText, NULL, &refStaticText);
-
- // Button Variables
- Rect bounds[numChoices];
- CFStringRef caption[numChoices];
- ControlRef button[numChoices];
-
- int whichButton=-1;
- CallbackData callbackData[numChoices];
-
- // Create the Buttons and assign event handlers
- for (int i = 0; i < numChoices; ++i) {
- bounds[i].top = 160 + ((CARBON_BUTTON_HEIGHT+CARBON_BUTTON_SPACING)*(i%iNumButtonRows));
- bounds[i].right = 530 - ((iButtonWidth+CARBON_BUTTON_SPACING)*(i/iNumButtonRows));
- bounds[i].left = bounds[i].right - iButtonWidth;
- bounds[i].bottom = bounds[i].top + CARBON_BUTTON_HEIGHT;
-
- // Convert the button captions to Apple strings
- caption[i] = CFStringCreateWithCString(kCFAllocatorDefault, choice[i], kCFStringEncodingUTF8);
-
- err = CreatePushButtonControl(window, &bounds[i], caption[i], &button[i]);
- assert(err == noErr);
-
- err = SetControlCommandID(button[i], CARBON_COMMANDID_START + i);
- assert(err == noErr);
-
- callbackData[i].refWindow = window;
- callbackData[i].myIndex = i;
- callbackData[i].whichButton = &whichButton;
-
- err = InstallControlEventHandler(button[i], buttonHandler,
- GetEventTypeCount(buttonSpec), buttonSpec,
- &callbackData[i], NULL);
- assert(err == noErr);
- }
-
- // Show Dialog
- err = RepositionWindow(window, NULL, kWindowCenterOnMainScreen);
- ShowWindow(window);
- BringToFront(window);
- err = ActivateWindow(window, true);
-
- // Hack to get our window/process to the front...
- ProcessSerialNumber psn = { 0, kCurrentProcess};
- TransformProcessType(&psn, kProcessTransformToForegroundApplication);
- SetFrontProcess (&psn);
-
- // Run in Modal State
- err = RunAppModalLoopForWindow(window);
-
- // Dispose of Button Related Data
- for (int i = 0; i < numChoices; ++i) {
- // Dispose of controls
- DisposeControl(button[i]);
-
- // Release CFStrings
- CFRelease(caption[i]);
- }
-
- // Dispose of Other Controls
- DisposeControl(refStaticText);
-
- // Dispose of Event Handlers
- DisposeEventHandlerUPP(buttonHandler);
-
- // Dispose of Window
- DisposeWindow(window);
-
- // Release CFStrings
- CFRelease(szWindowTitle);
- CFRelease(szStaticText);
-
- // Return Selection
- return whichButton;
+
+ return prompt_cocoa(windowTitle, prompt, choice, numChoices);
}
#endif
#endif /* G3DFIX: exclude GUI prompt code */
-
int prompt(
const char* windowTitle,
const char* prompt,
@@ -704,7 +557,7 @@ int prompt(
int numChoices,
bool useGui) {
#if 0 /* G3DFIX: exclude GUI prompt code */
- #ifdef G3D_WIN32
+ #ifdef G3D_WINDOWS
if (useGui) {
// Build the message box
return guiPrompt(windowTitle, prompt, choice, numChoices);
@@ -713,8 +566,10 @@ int prompt(
#ifdef G3D_OSX
if (useGui){
- //Will default to text prompt if numChoices > 4
- return guiPrompt(windowTitle, prompt, choice, numChoices);
+ //Will default to text prompt if numChoices > 4
+ int result = guiPrompt(windowTitle, prompt, choice, numChoices);
+ fprintf(stderr, "%d\n", result);
+ return result;
}
#endif
#endif /* G3DFIX: exclude GUI prompt code */
@@ -730,9 +585,9 @@ void msgBox(
prompt(title.c_str(), message.c_str(), choice, 1, true);
}
-#ifndef G3D_WIN32
+#ifndef G3D_WINDOWS
#undef _getch
#endif
-};// namespace
+}// namespace
diff --git a/dep/g3dlite/source/stringutils.cpp b/dep/g3dlite/source/stringutils.cpp
index c3876ebb6a4..ff71851700c 100644
--- a/dep/g3dlite/source/stringutils.cpp
+++ b/dep/g3dlite/source/stringutils.cpp
@@ -1,10 +1,10 @@
/**
- @file stringutils.cpp
+ \file stringutils.cpp
- @maintainer Morgan McGuire, http://graphics.cs.williams.edu
+ \maintainer Morgan McGuire, http://graphics.cs.williams.edu
- @created 2000-09-09
- @edited 2008-01-10
+ \created 2000-09-09
+ \edited 2011-08-20
*/
#include "G3D/platform.h"
@@ -12,6 +12,14 @@
#include "G3D/BinaryInput.h"
#include <algorithm>
+#ifdef G3D_WINDOWS
+extern "C" {
+ // Define functions for ffmpeg since we don't link in gcc's c library
+ extern int strncasecmp(const char *string1, const char *string2, size_t count) { return _strnicmp(string1, string2, count); }
+ extern int strcasecmp(const char *string1, const char *string2) { return _stricmp(string1, string2); }
+}
+#endif
+
namespace G3D {
#ifdef _MSC_VER
@@ -19,7 +27,7 @@ namespace G3D {
# pragma warning (push)
# pragma warning (disable : 4530)
#endif
-#ifdef G3D_WIN32
+#ifdef G3D_WINDOWS
const char* NEWLINE = "\r\n";
#else
const char* NEWLINE = "\n";
@@ -56,7 +64,7 @@ void parseCommaSeparated(const std::string s, Array<std::string>& array, bool st
if (stripQuotes) {
for (int i = 0; i < array.length(); ++i) {
std::string& t = array[i];
- int L = t.length();
+ size_t L = t.length();
if ((L > 1) && (t[0] == quote) && (t[L - 1] == quote)) {
if ((L > 6) && (t[1] == quote) && (t[2] == quote) && (t[L - 3] == quote) && (t[L - 2] == quote)) {
// Triple-quote
@@ -86,15 +94,44 @@ bool beginsWith(
}
}
+std::string replace(const std::string& s, const std::string& pattern, const std::string& replacement) {
+ if (pattern.length() == 0) {
+ return s;
+ }
+ std::string temp = "";
+ size_t lastindex = 0;
+ size_t nextindex = 0;
+ do {
+ nextindex = s.find(pattern, lastindex);
+ if (nextindex == std::string::npos) {
+ break;
+ }
+ temp += s.substr(lastindex, nextindex - lastindex) + replacement;
+ lastindex = nextindex + pattern.length();
+ } while (lastindex + pattern.length() <= s.length());
+ return temp + (lastindex < s.length() ? s.substr(lastindex) : "");
+}
+
+bool isValidIdentifier(const std::string& s) {
+ if (s.length() > 0 && (isLetter(s[0]) || s[0] == '_')) {
+ for (size_t i = 1; i < s.length() ; ++i) {
+ if (!( isLetter(s[i]) || (s[i] == '_') || isDigit(s[i]) )) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
bool endsWith(
const std::string& test,
const std::string& pattern) {
if (test.size() >= pattern.size()) {
- int te = test.size() - 1;
- int pe = pattern.size() - 1;
- for (int i = pattern.size() - 1; i >= 0; --i) {
+ size_t te = test.size() - 1;
+ size_t pe = pattern.size() - 1;
+ for (int i = (int)pattern.size() - 1; i >= 0; --i) {
if (pattern[pe - i] != test[te - i]) {
return false;
}
@@ -151,7 +188,7 @@ std::string wordWrap(
if (c < input.size()) {
// Collapse multiple spaces.
while ((input[c] == ' ') && (c < input.size())) {
- c++;
+ ++c;
}
}
}
@@ -248,9 +285,11 @@ std::string stringJoin(
}
-std::string trimWhitespace(
- const std::string& s) {
+std::string trimWhitespace(const std::string& s) {
+ if (s.length() == 0) {
+ return s;
+ }
size_t left = 0;
// Trim from left
@@ -258,15 +297,16 @@ std::string trimWhitespace(
++left;
}
- int right = s.length() - 1;
+ size_t right = s.length() - 1;
// Trim from right
- while ((right > (int)left) && iswspace(s[right])) {
+ while ((right > left) && iswspace(s[right])) {
--right;
}
return s.substr(left, right - left + 1);
}
+
}; // namespace
#undef NEWLINE
diff --git a/dep/g3dlite/source/uint128.cpp b/dep/g3dlite/source/uint128.cpp
index 1f596fc3e51..2fd58a332cd 100644
--- a/dep/g3dlite/source/uint128.cpp
+++ b/dep/g3dlite/source/uint128.cpp
@@ -17,8 +17,8 @@ static void addAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint6
// Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros.
// This eliminates the need to and with 0xFFFFFFFF.
- uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32};
- uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32};
+ uint32 a [2] = {static_cast<uint32>(_a & 0xFFFFFFFF), static_cast<uint32>(_a >> 32)};
+ uint32 b [2] = {static_cast<uint32>(_b & 0xFFFFFFFF), static_cast<uint32>(_b >> 32)};
uint64 tmp = uint64(a[0]) + b[0];
@@ -35,8 +35,8 @@ void multiplyAndCarry(const uint64& _a, const uint64& _b, uint64& carry, uint64&
// Break each number into 4 32-bit chunks. Since we are using uints, right-shifting will fill with zeros.
// This eliminates the need to and with 0xFFFFFFFF.
- uint32 a [2] = {_a & 0xFFFFFFFF, _a >> 32};
- uint32 b [2] = {_b & 0xFFFFFFFF, _b >> 32};
+ uint32 a [2] = {static_cast<uint32>(_a & 0xFFFFFFFF), static_cast<uint32>(_a >> 32)};
+ uint32 b [2] = {static_cast<uint32>(_b & 0xFFFFFFFF), static_cast<uint32>(_b >> 32)};
uint64 prod [2][2];
for(int i = 0; i < 2; ++i) {