From 27cdcd9ada874f56d5be16097e3f09e74df788e4 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 17:03:38 +0200 Subject: [PATCH 1/6] Fix compiler warnings for g++ 4.7. This fixes nine compiler warnings like: /opt/highfidelity/hifi/hifi/libraries/particles/src/Particle.cpp:371:43: warning: comparison between signed and unsigned integer expressions [-Wsign-compare] The best way to avoid this (without using an ugly (int) cast) is to bring everything to one side and compare with zero, which results in the same assembly code after optimization (it's the same to the compiler). --- libraries/particles/src/Particle.cpp | 40 ++++++++++++++-------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 76890afafe..814da636c1 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -368,7 +368,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr uint32_t editID; // check to make sure we have enough content to keep reading... - if (processedBytes + sizeof(editID) > length) { + if (length - processedBytes - sizeof(editID) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -387,7 +387,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr uint32_t creatorTokenID; // check to make sure we have enough content to keep reading... - if (processedBytes + sizeof(creatorTokenID) > length) { + if (length - processedBytes - sizeof(creatorTokenID) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -426,7 +426,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // lastEdited // check to make sure we have enough content to keep reading... - if (processedBytes + sizeof(newParticle._lastEdited) > length) { + if (length - processedBytes - sizeof(newParticle._lastEdited) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -439,7 +439,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // properties included bits uint16_t packetContainsBits = 0; if (!isNewParticle) { - if (processedBytes + sizeof(packetContainsBits) > length) { + if (length - processedBytes - sizeof(packetContainsBits) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -452,7 +452,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // radius if (isNewParticle || ((packetContainsBits & CONTAINS_RADIUS) == CONTAINS_RADIUS)) { - if (processedBytes + sizeof(newParticle._radius) > length) { + if (length - processedBytes - sizeof(newParticle._radius) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -464,7 +464,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // position if (isNewParticle || ((packetContainsBits & CONTAINS_POSITION) == CONTAINS_POSITION)) { - if (processedBytes + sizeof(newParticle._position) > length) { + if (length - processedBytes - sizeof(newParticle._position) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -476,7 +476,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // color if (isNewParticle || ((packetContainsBits & CONTAINS_COLOR) == CONTAINS_COLOR)) { - if (processedBytes + sizeof(newParticle._color) > length) { + if (length - processedBytes - sizeof(newParticle._color) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -488,7 +488,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // velocity if (isNewParticle || ((packetContainsBits & CONTAINS_VELOCITY) == CONTAINS_VELOCITY)) { - if (processedBytes + sizeof(newParticle._velocity) > length) { + if (length - processedBytes - sizeof(newParticle._velocity) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -500,7 +500,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // gravity if (isNewParticle || ((packetContainsBits & CONTAINS_GRAVITY) == CONTAINS_GRAVITY)) { - if (processedBytes + sizeof(newParticle._gravity) > length) { + if (length - processedBytes - sizeof(newParticle._gravity) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -512,7 +512,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // damping if (isNewParticle || ((packetContainsBits & CONTAINS_DAMPING) == CONTAINS_DAMPING)) { - if (processedBytes + sizeof(newParticle._damping) > length) { + if (length - processedBytes - sizeof(newParticle._damping) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -524,7 +524,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // lifetime if (isNewParticle || ((packetContainsBits & CONTAINS_LIFETIME) == CONTAINS_LIFETIME)) { - if (processedBytes + sizeof(newParticle._lifetime) > length) { + if (length - processedBytes - sizeof(newParticle._lifetime) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -537,7 +537,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // TODO: make inHand and shouldDie into single bits // inHand if (isNewParticle || ((packetContainsBits & CONTAINS_INHAND) == CONTAINS_INHAND)) { - if (processedBytes + sizeof(newParticle._inHand) > length) { + if (length - processedBytes - sizeof(newParticle._inHand) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -549,7 +549,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // shouldDie if (isNewParticle || ((packetContainsBits & CONTAINS_SHOULDDIE) == CONTAINS_SHOULDDIE)) { - if (processedBytes + sizeof(newParticle._shouldDie) > length) { + if (length - processedBytes - sizeof(newParticle._shouldDie) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -562,7 +562,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // script if (isNewParticle || ((packetContainsBits & CONTAINS_SCRIPT) == CONTAINS_SCRIPT)) { uint16_t scriptLength; - if (processedBytes + sizeof(scriptLength) > length) { + if (length - processedBytes - sizeof(scriptLength) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -571,7 +571,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr dataAt += sizeof(scriptLength); processedBytes += sizeof(scriptLength); - if (processedBytes + scriptLength > length) { + if (length - processedBytes - scriptLength < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -585,7 +585,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelURL if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_URL) == CONTAINS_MODEL_URL)) { uint16_t modelURLLength; - if (processedBytes + sizeof(modelURLLength) > length) { + if (length - processedBytes - sizeof(modelURLLength) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -594,7 +594,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr dataAt += sizeof(modelURLLength); processedBytes += sizeof(modelURLLength); - if (processedBytes + modelURLLength > length) { + if (length - processedBytes - modelURLLength < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -607,7 +607,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelScale if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_SCALE) == CONTAINS_MODEL_SCALE)) { - if (processedBytes + sizeof(newParticle._modelScale) > length) { + if (length - processedBytes - sizeof(newParticle._modelScale) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -619,7 +619,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelTranslation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_TRANSLATION) == CONTAINS_MODEL_TRANSLATION)) { - if (processedBytes + sizeof(newParticle._modelTranslation) > length) { + if (length - processedBytes - sizeof(newParticle._modelTranslation) < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer @@ -632,7 +632,7 @@ Particle Particle::fromEditPacket(const unsigned char* data, int length, int& pr // modelRotation if (isNewParticle || ((packetContainsBits & CONTAINS_MODEL_ROTATION) == CONTAINS_MODEL_ROTATION)) { const int expectedBytesForPackedQuat = sizeof(uint16_t) * 4; // this is how we pack the quats - if (processedBytes + expectedBytesForPackedQuat > length) { + if (length - processedBytes - expectedBytesForPackedQuat < 0) { valid = false; processedBytes = length; return newParticle; // fail as if we read the entire buffer From bd212c26d0960e9a29eaf9e628b693d22a62a6ac Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 17:10:39 +0200 Subject: [PATCH 2/6] Fix initializer list order (avoiding compiler warning). MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This patch fixes the compiler warning: In file included from /opt/highfidelity/hifi/hifi/interface/src/Application.h:45:0, from /opt/highfidelity/hifi/hifi/interface/src/Audio.cpp:42: /opt/highfidelity/hifi/hifi/interface/src/Audio.h: In constructor ‘Audio::Audio(int16_t, QObject*)’: /opt/highfidelity/hifi/hifi/interface/src/Audio.h:268:30: warning: ‘Audio::_interframeTimeGapStats’ will be initialized after [-Wreorder] /opt/highfidelity/hifi/hifi/interface/src/Audio.h:259:9: warning: ‘int Audio::_starveCount’ [-Wreorder] /opt/highfidelity/hifi/hifi/interface/src/Audio.cpp:63:1: warning: when initialized here [-Wreorder] by fixing the initializer list of class Audio. Note that I omitted _audioMixerAvatarStreamAudioStats() - which is a default constructor that is called anyway (it's the default!) and therefore doesn't belong in the initializer list. --- interface/src/Audio.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 3689ff0143..6a26563e36 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -112,12 +112,11 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) : _scopeInput(0), _scopeOutputLeft(0), _scopeOutputRight(0), - _audioMixerAvatarStreamAudioStats(), + _starveCount(0), + _consecutiveNotMixedCount(0), _outgoingAvatarAudioSequenceNumber(0), _incomingMixedAudioSequenceNumberStats(INCOMING_SEQ_STATS_HISTORY_LENGTH), - _interframeTimeGapStats(TIME_GAPS_STATS_INTERVAL_SAMPLES, TIME_GAP_STATS_WINDOW_INTERVALS), - _starveCount(0), - _consecutiveNotMixedCount(0) + _interframeTimeGapStats(TIME_GAPS_STATS_INTERVAL_SAMPLES, TIME_GAP_STATS_WINDOW_INTERVALS) { // clear the array of locally injected samples memset(_localProceduralSamples, 0, NETWORK_BUFFER_LENGTH_BYTES_PER_CHANNEL); From ea98b58b405b1599b1d55449b4b0b3a097fe7cc4 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 20:29:01 +0200 Subject: [PATCH 3/6] Debug support: allow printing of glm types to QDebug. This adds support for serialization to QDebug of glm::vec3, glm::quat and glm::mat4. Output example: qDebug().nospace() << "Calling PhysicsEntity::findRayIntersection(" << origin << ", " << direction << ", &distance) const; numShapes = " << numShapes; leads to: [2014-07-13T20:24:47] Calling PhysicsEntity::findRayIntersection({type='glm::vec3', x=5222.45, y=2159.05, z=6527.79}, {type='glm::vec3', x=0, y=-0.119145, z=-0.992877}, &distance) const; numShapes = 0 Note that we explicitly don't return dbg.space() because we want to be able to print these things comma separated as follows: {...}, {...}, ... as opposed to {...} , {...} etc. I changed the already existing operator<< for Box to the more general case, where it just prints its members and doesn't mess with the internals of its members. The result is more verbose, but also more recognizable when in the future everything will look the same, allowing for speed reading the debug output. The constructor of Box needed to made explicit because it was too annoying that when one forgets to #include "StreamUtils.h" that writing a glm::vec3 resulted in printing out a Box, implicitly converted from the vector. --- libraries/metavoxels/src/MetavoxelUtil.cpp | 6 ++--- libraries/metavoxels/src/MetavoxelUtil.h | 2 +- libraries/shared/src/StreamUtils.cpp | 31 ++++++++++++++++++++++ libraries/shared/src/StreamUtils.h | 13 ++++++--- 4 files changed, 45 insertions(+), 7 deletions(-) diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp index f2f434b24d..b0233f04cd 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ b/libraries/metavoxels/src/MetavoxelUtil.cpp @@ -26,6 +26,7 @@ #include "MetavoxelUtil.h" #include "ScriptCache.h" +#include "StreamUtils.h" static int scriptHashType = qRegisterMetaType(); static int parameterizedURLType = qRegisterMetaType(); @@ -310,9 +311,8 @@ Box operator*(const glm::mat4& matrix, const Box& box) { return newBox; } -QDebug& operator<<(QDebug& out, const Box& box) { - return out << '(' << box.minimum.x << box.minimum.y << box.minimum.z << ") (" << - box.maximum.x << box.maximum.y << box.maximum.z << ')'; +QDebug& operator<<(QDebug& dbg, const Box& box) { + return dbg.nospace() << "{type='Box', minimum=" << box.minimum << ", maximumx=" << box.maximum << "}"; } QMetaObjectEditor::QMetaObjectEditor(QWidget* parent) : QWidget(parent) { diff --git a/libraries/metavoxels/src/MetavoxelUtil.h b/libraries/metavoxels/src/MetavoxelUtil.h index 34c2bac6be..83aac1318e 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.h +++ b/libraries/metavoxels/src/MetavoxelUtil.h @@ -42,7 +42,7 @@ public: STREAM glm::vec3 minimum; STREAM glm::vec3 maximum; - Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3()); + explicit Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3()); bool contains(const glm::vec3& point) const; diff --git a/libraries/shared/src/StreamUtils.cpp b/libraries/shared/src/StreamUtils.cpp index 5356c45a51..1723068eee 100644 --- a/libraries/shared/src/StreamUtils.cpp +++ b/libraries/shared/src/StreamUtils.cpp @@ -95,3 +95,34 @@ std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule) { #endif // DEBUG +#ifndef QT_NO_DEBUG_STREAM +#include + +QDebug& operator<<(QDebug& dbg, const glm::vec3& v) { + dbg.nospace() << "{type='glm::vec3'" + ", x=" << v.x << + ", y=" << v.y << + ", z=" << v.z << + "}"; + return dbg; +} + +QDebug& operator<<(QDebug& dbg, const glm::quat& q) { + dbg.nospace() << "{type='glm::quat'" + ", x=" << q.x << + ", y=" << q.y << + ", z=" << q.z << + ", w=" << q.w << + "}"; + return dbg; +} + +QDebug& operator<<(QDebug& dbg, const glm::mat4& m) { + dbg.nospace() << "{type='glm::mat4', ["; + for (int j = 0; j < 4; ++j) { + dbg << ' ' << m[0][j] << ' ' << m[1][j] << ' ' << m[2][j] << ' ' << m[3][j] << ';'; + } + return dbg << " ]}"; +} + +#endif // QT_NO_DEBUG_STREAM diff --git a/libraries/shared/src/StreamUtils.h b/libraries/shared/src/StreamUtils.h index 2a42a3ea7b..4f74e895d2 100644 --- a/libraries/shared/src/StreamUtils.h +++ b/libraries/shared/src/StreamUtils.h @@ -38,13 +38,20 @@ QDataStream& operator>>(QDataStream& in, glm::quat& quaternion); // less common utils can be enabled with DEBUG #ifdef DEBUG -#include "CollisionInfo.h" -#include "SphereShape.h" -#include "CapsuleShape.h" +class CollisionInfo; +class SphereShape; +class CapsuleShape.h; std::ostream& operator<<(std::ostream& s, const CollisionInfo& c); std::ostream& operator<<(std::ostream& s, const SphereShape& shape); std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule); #endif // DEBUG +#ifndef QT_NO_DEBUG_STREAM +class QDebug; +// Add support for writing these to qDebug()> +QDebug& operator<<(QDebug& s, const glm::vec3& v); +QDebug& operator<<(QDebug& s, const glm::quat& q); +QDebug& operator<<(QDebug& s, const glm::mat4& m); +#endif // QT_NO_DEBUG_STREAM #endif // hifi_StreamUtils_h From 961eca432746bc8e1fb1b949d04cb7c8d3ef2de7 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 20:51:19 +0200 Subject: [PATCH 4/6] Fix typo in previous commit --- libraries/metavoxels/src/MetavoxelUtil.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/metavoxels/src/MetavoxelUtil.cpp b/libraries/metavoxels/src/MetavoxelUtil.cpp index b0233f04cd..d35b9a698a 100644 --- a/libraries/metavoxels/src/MetavoxelUtil.cpp +++ b/libraries/metavoxels/src/MetavoxelUtil.cpp @@ -312,7 +312,7 @@ Box operator*(const glm::mat4& matrix, const Box& box) { } QDebug& operator<<(QDebug& dbg, const Box& box) { - return dbg.nospace() << "{type='Box', minimum=" << box.minimum << ", maximumx=" << box.maximum << "}"; + return dbg.nospace() << "{type='Box', minimum=" << box.minimum << ", maximum=" << box.maximum << "}"; } QMetaObjectEditor::QMetaObjectEditor(QWidget* parent) : QWidget(parent) { From 13c2c69d0666805a9324a59468037dbe7cd90ba9 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 20:54:27 +0200 Subject: [PATCH 5/6] Fix another typo in previous commit --- libraries/shared/src/StreamUtils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/StreamUtils.h b/libraries/shared/src/StreamUtils.h index 4f74e895d2..c9356eaca2 100644 --- a/libraries/shared/src/StreamUtils.h +++ b/libraries/shared/src/StreamUtils.h @@ -48,7 +48,7 @@ std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule); #ifndef QT_NO_DEBUG_STREAM class QDebug; -// Add support for writing these to qDebug()> +// Add support for writing these to qDebug(). QDebug& operator<<(QDebug& s, const glm::vec3& v); QDebug& operator<<(QDebug& s, const glm::quat& q); QDebug& operator<<(QDebug& s, const glm::mat4& m); From 147a4119cbdf8532ed61608a62d9536eca202f77 Mon Sep 17 00:00:00 2001 From: Aleric Inglewood Date: Sun, 13 Jul 2014 21:54:07 +0200 Subject: [PATCH 6/6] Fix linker problem This fixes the linker problem: /usr/bin/ld: error: ../../libraries/shared/libshared.a(StreamUtils.cpp.o): multiple definition of 'operator<<(std::ostream&, glm::detail::tvec3 const&)' /usr/bin/ld: CMakeFiles/physics-tests.dir/src/PhysicsTestUtil.cpp.o: previous definition here /usr/bin/ld: error: ../../libraries/shared/libshared.a(StreamUtils.cpp.o): multiple definition of 'operator<<(std::ostream&, glm::detail::tquat const&)' /usr/bin/ld: CMakeFiles/physics-tests.dir/src/PhysicsTestUtil.cpp.o: previous definition here /usr/bin/ld: error: ../../libraries/shared/libshared.a(StreamUtils.cpp.o): multiple definition of 'operator<<(std::ostream&, glm::detail::tmat4x4 const&)' /usr/bin/ld: CMakeFiles/physics-tests.dir/src/PhysicsTestUtil.cpp.o: previous definition here collect2: error: ld returned 1 exit status Note these are the serializers to std::ostream that were already there, not the ones that I added (which are to QDebug). This bug was already there, I only got these errors now after adding some debug code. The reason is obvious: they are already defined in libshared.a (through StreamUtils.cpp). No need to define them again in ./tests/physics/src/PhysicsTestUtil.cpp --- tests/physics/src/PhysicsTestUtil.cpp | 20 +------------------- tests/physics/src/PhysicsTestUtil.h | 3 --- 2 files changed, 1 insertion(+), 22 deletions(-) diff --git a/tests/physics/src/PhysicsTestUtil.cpp b/tests/physics/src/PhysicsTestUtil.cpp index f176d5e637..a11d4f2add 100644 --- a/tests/physics/src/PhysicsTestUtil.cpp +++ b/tests/physics/src/PhysicsTestUtil.cpp @@ -12,25 +12,7 @@ #include #include "PhysicsTestUtil.h" - -std::ostream& operator<<(std::ostream& s, const glm::vec3& v) { - s << "<" << v.x << "," << v.y << "," << v.z << ">"; - return s; -} - -std::ostream& operator<<(std::ostream& s, const glm::quat& q) { - s << "<" << q.x << "," << q.y << "," << q.z << "," << q.w << ">"; - return s; -} - -std::ostream& operator<<(std::ostream& s, const glm::mat4& m) { - s << "["; - for (int j = 0; j < 4; ++j) { - s << " " << m[0][j] << " " << m[1][j] << " " << m[2][j] << " " << m[3][j] << ";"; - } - s << " ]"; - return s; -} +#include "StreamUtils.h" std::ostream& operator<<(std::ostream& s, const CollisionInfo& c) { s << "[penetration=" << c._penetration diff --git a/tests/physics/src/PhysicsTestUtil.h b/tests/physics/src/PhysicsTestUtil.h index 998a18ff5d..c93545dd76 100644 --- a/tests/physics/src/PhysicsTestUtil.h +++ b/tests/physics/src/PhysicsTestUtil.h @@ -21,9 +21,6 @@ const glm::vec3 xAxis(1.f, 0.f, 0.f); const glm::vec3 yAxis(0.f, 1.f, 0.f); const glm::vec3 zAxis(0.f, 0.f, 1.f); -std::ostream& operator<<(std::ostream& s, const glm::vec3& v); -std::ostream& operator<<(std::ostream& s, const glm::quat& q); -std::ostream& operator<<(std::ostream& s, const glm::mat4& m); std::ostream& operator<<(std::ostream& s, const CollisionInfo& c); #endif // hifi_PhysicsTestUtil_h