From dd02bae5b32bb6de15f6b7c92a8abf11ebabce00 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 15 Apr 2014 16:11:00 -0700 Subject: [PATCH 01/76] First cut at improved undo --- libraries/voxels/src/VoxelTreeCommands.cpp | 84 +++++++++++++++++----- libraries/voxels/src/VoxelTreeCommands.h | 4 ++ 2 files changed, 70 insertions(+), 18 deletions(-) diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index f0f092fd04..75b38667ec 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -17,8 +17,37 @@ AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditP QUndoCommand("Add Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel) + _voxel(voxel), + _oldTree(NULL) { + VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element) { + if (element->hasContent() && element->isLeaf()) { + // Do nothing, everything is in order + } else { + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, true); + } + } else { + glm::vec3 point(_voxel.x + _voxel.s / 2.0f, + _voxel.y + _voxel.s / 2.0f, + _voxel.z + _voxel.s / 2.0f); + OctreeElement* element = _tree->getElementEnclosingPoint(point, Octree::Lock); + if (element) { + VoxelTreeElement* node = static_cast(element); + _voxel.x = node->getCorner().x; + _voxel.y = node->getCorner().y; + _voxel.z = node->getCorner().z; + _voxel.s = node->getScale(); + _voxel.red = node->getColor()[0]; + _voxel.green = node->getColor()[1]; + _voxel.blue = node->getColor()[2]; + } + } +} + +AddVoxelCommand::~AddVoxelCommand() { + delete _oldTree; } void AddVoxelCommand::redo() { @@ -31,11 +60,17 @@ void AddVoxelCommand::redo() { } void AddVoxelCommand::undo() { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + if (_oldTree) { + OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + qDebug() << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; + _tree->copyFromTreeIntoSubTree(_oldTree, element); + } else { + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + } } } @@ -43,24 +78,37 @@ DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, Voxe QUndoCommand("Delete Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel) + _voxel(voxel), + _oldTree(NULL) { } +DeleteVoxelCommand::~DeleteVoxelCommand() { + delete _oldTree; +} + void DeleteVoxelCommand::redo() { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + if (_oldTree) { + + } else { + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); + } } } void DeleteVoxelCommand::undo() { - if (_tree) { - _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); + if (_oldTree) { + + } else { + if (_tree) { + _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); + } } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); - } -} +} \ No newline at end of file diff --git a/libraries/voxels/src/VoxelTreeCommands.h b/libraries/voxels/src/VoxelTreeCommands.h index 4f2610577e..c3b23e7201 100644 --- a/libraries/voxels/src/VoxelTreeCommands.h +++ b/libraries/voxels/src/VoxelTreeCommands.h @@ -23,6 +23,7 @@ class VoxelTree; class AddVoxelCommand : public QUndoCommand { public: AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); + ~AddVoxelCommand(); virtual void redo(); virtual void undo(); @@ -31,11 +32,13 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; + VoxelTree* _oldTree; }; class DeleteVoxelCommand : public QUndoCommand { public: DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); + ~DeleteVoxelCommand(); virtual void redo(); virtual void undo(); @@ -44,6 +47,7 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; + VoxelTree* _oldTree; }; #endif // hifi_VoxelTreeCommands_h From d34e6ff86483125a0ac9e554ad7f5a323688546c Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 16 Apr 2014 12:01:41 -0700 Subject: [PATCH 02/76] Removed gettimeofday in AudioInjector --- libraries/audio/src/AudioInjector.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 6370e51826..eed41ac849 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -71,8 +71,8 @@ void AudioInjector::injectAudio() { quint8 volume = MAX_INJECTOR_VOLUME * _options.getVolume(); packetStream << volume; - timeval startTime = {}; - gettimeofday(&startTime, NULL); + QElapsedTimer timer; + timer.start(); int nextFrame = 0; int currentSendPosition = 0; @@ -104,7 +104,7 @@ void AudioInjector::injectAudio() { if (currentSendPosition != bytesToCopy && currentSendPosition < soundByteArray.size()) { // not the first packet and not done // sleep for the appropriate time - int usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); + int usecToSleep = (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - timer.nsecsElapsed() / 1000; if (usecToSleep > 0) { usleep(usecToSleep); From 8cfc8faa019bf5a583fd8bcb93ea47627800f060 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 16 Apr 2014 12:08:17 -0700 Subject: [PATCH 03/76] Removed gettimeofday in Audio --- interface/src/Audio.cpp | 13 +++++-------- interface/src/Audio.h | 3 ++- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 5dcd54050c..c7f7c2c354 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -616,12 +616,11 @@ void Audio::handleAudioInput() { void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { const int NUM_INITIAL_PACKETS_DISCARD = 3; const int STANDARD_DEVIATION_SAMPLE_COUNT = 500; - - timeval currentReceiveTime; - gettimeofday(¤tReceiveTime, NULL); + + _timeSinceLastRecieved.start(); _totalPacketsReceived++; - - double timeDiff = diffclock(&_lastReceiveTime, ¤tReceiveTime); + + double timeDiff = (double)_timeSinceLastRecieved.nsecsElapsed() / 1000000.0; // ns to ms // Discard first few received packets for computing jitter (often they pile up on start) if (_totalPacketsReceived > NUM_INITIAL_PACKETS_DISCARD) { @@ -646,8 +645,6 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { } Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::AUDIO).updateValue(audioByteArray.size()); - - _lastReceiveTime = currentReceiveTime; } bool Audio::mousePressEvent(int x, int y) { @@ -995,7 +992,7 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) // setup a procedural audio output device _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - gettimeofday(&_lastReceiveTime, NULL); + _timeSinceLastRecieved.start(); supportedFormat = true; } } diff --git a/interface/src/Audio.h b/interface/src/Audio.h index b78bcc661e..3fa4175573 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -123,7 +124,7 @@ private: QString _outputAudioDeviceName; StDev _stdev; - timeval _lastReceiveTime; + QElapsedTimer _timeSinceLastRecieved; float _averagedLatency; float _measuredJitter; int16_t _jitterBufferSamples; From dd8a0e355055476af97f6f668d451b4182e4e5a4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 16 Apr 2014 12:16:49 -0700 Subject: [PATCH 04/76] Removed gettimeofday in AudioMixer --- assignment-client/src/audio/AudioMixer.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 407a64d7a8..65d09f1b00 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -389,9 +389,8 @@ void AudioMixer::run() { nodeList->linkedDataCreateCallback = attachNewBufferToNode; int nextFrame = 0; - timeval startTime; - - gettimeofday(&startTime, NULL); + QElapsedTimer timer; + timer.start(); char* clientMixBuffer = new char[NETWORK_BUFFER_LENGTH_BYTES_STEREO + numBytesForPacketHeaderGivenPacketType(PacketTypeMixedAudio)]; @@ -490,7 +489,7 @@ void AudioMixer::run() { break; } - usecToSleep = usecTimestamp(&startTime) + (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - usecTimestampNow(); + usecToSleep = (++nextFrame * BUFFER_SEND_INTERVAL_USECS) - timer.nsecsElapsed() / 1000; // ns to us if (usecToSleep > 0) { usleep(usecToSleep); From 30248747d6475bed432318f8fee77a7741cd8d46 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 18 Apr 2014 14:26:34 -0700 Subject: [PATCH 05/76] Provide a means of visualizing the joint constraints. --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/MyAvatar.cpp | 3 ++ interface/src/avatar/SkeletonModel.cpp | 61 ++++++++++++++++++++++++++ interface/src/avatar/SkeletonModel.h | 4 ++ 5 files changed, 70 insertions(+) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index b05e5c91bc..bb20a469b4 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -330,6 +330,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::DisplayHandTargets, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::PlaySlaps, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false); + addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false); addDisabledActionAndSeparator(developerMenu, "Testing"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index c17c9cc507..710cc5d78b 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -348,6 +348,7 @@ namespace MenuOption { const QString SettingsImport = "Import Settings"; const QString Shadows = "Shadows"; const QString ShowCulledSharedFaces = "Show Culled Shared Voxel Faces"; + const QString ShowIKConstraints = "Show IK Constraints"; const QString Stars = "Stars"; const QString Stats = "Stats"; const QString StopAllScripts = "Stop All Scripts"; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8229611646..a8d6dfa242 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -460,6 +460,9 @@ void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { return; // exit early } Avatar::render(cameraPosition, renderMode); + if (Menu::getInstance()->isOptionChecked(MenuOption::ShowIKConstraints)) { + _skeletonModel.renderIKConstraints(); + } } void MyAvatar::renderHeadMouse() const { diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index b9ac280711..8d593a9c02 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -103,6 +103,11 @@ void SkeletonModel::getBodyShapes(QVector& shapes) const { shapes.push_back(&_boundingShape); } +void SkeletonModel::renderIKConstraints() { + renderJointConstraints(getRightHandJointIndex()); + renderJointConstraints(getLeftHandJointIndex()); +} + class IndexValue { public: int index; @@ -210,3 +215,59 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const glm::normalize(inverse * axes[0])) * joint.rotation; } +void SkeletonModel::renderJointConstraints(int jointIndex) { + if (jointIndex == -1) { + return; + } + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const float BASE_DIRECTION_SIZE = 300.0f; + float directionSize = BASE_DIRECTION_SIZE * extractUniformScale(_scale); + glLineWidth(3.0f); + do { + const FBXJoint& joint = geometry.joints.at(jointIndex); + const JointState& jointState = _jointStates.at(jointIndex); + glm::vec3 position = extractTranslation(jointState.transform) + _translation; + + glPushMatrix(); + glTranslatef(position.x, position.y, position.z); + glm::quat parentRotation = (joint.parentIndex == -1) ? _rotation : _jointStates.at(joint.parentIndex).combinedRotation; + glm::vec3 rotationAxis = glm::axis(parentRotation); + glRotatef(glm::degrees(glm::angle(parentRotation)), rotationAxis.x, rotationAxis.y, rotationAxis.z); + float fanScale = directionSize * 0.75f; + glScalef(fanScale, fanScale, fanScale); + const int AXIS_COUNT = 3; + for (int i = 0; i < AXIS_COUNT; i++) { + if (joint.rotationMin[i] <= -PI + EPSILON && joint.rotationMax[i] >= PI - EPSILON) { + continue; // unconstrained + } + glm::vec3 axis; + axis[i] = 1.0f; + + glm::vec3 otherAxis; + if (i == 0) { + otherAxis.y = 1.0f; + } else { + otherAxis.x = 1.0f; + } + glColor4f(otherAxis.r, otherAxis.g, otherAxis.b, 0.75f); + + glBegin(GL_TRIANGLE_FAN); + glVertex3f(0.0f, 0.0f, 0.0f); + const int FAN_SEGMENTS = 16; + for (int j = 0; j < FAN_SEGMENTS; j++) { + glm::vec3 rotated = glm::angleAxis(glm::mix(joint.rotationMin[i], joint.rotationMax[i], + (float)j / (FAN_SEGMENTS - 1)), axis) * otherAxis; + glVertex3f(rotated.x, rotated.y, rotated.z); + } + glEnd(); + } + glPopMatrix(); + + renderOrientationDirections(position, jointState.combinedRotation, directionSize); + jointIndex = joint.parentIndex; + + } while (jointIndex != -1 && geometry.joints.at(jointIndex).isFree); + + glLineWidth(1.0f); +} + diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 2020ccf3b2..0a87fcf89d 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -33,6 +33,8 @@ public: /// \param shapes[out] list of shapes for body collisions void getBodyShapes(QVector& shapes) const; + void renderIKConstraints(); + protected: void applyHandPosition(int jointIndex, const glm::vec3& position); @@ -46,6 +48,8 @@ protected: virtual void maybeUpdateLeanRotation(const JointState& parentState, const FBXJoint& joint, JointState& state); private: + + void renderJointConstraints(int jointIndex); Avatar* _owningAvatar; }; From 6add0dfb4271360d1d3dff82fbf4f61a67041934 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 18 Apr 2014 15:04:42 -0700 Subject: [PATCH 06/76] Tweaked Hydra "IK" to propagate delta rotations up the hierarchy while preserving joint constraints. --- interface/src/avatar/SkeletonModel.cpp | 7 ++++--- interface/src/renderer/Model.cpp | 13 ++++++++++--- interface/src/renderer/Model.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 8d593a9c02..1c6a568754 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -138,7 +138,7 @@ void SkeletonModel::applyHandPosition(int jointIndex, const glm::vec3& position) // align hand with forearm float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector), false); + applyRotationDelta(jointIndex, rotationBetween(handRotation * glm::vec3(-sign, 0.0f, 0.0f), forearmVector)); } void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJointIndices, @@ -156,7 +156,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin // rotate forearm to align with palm direction glm::quat palmRotation; getJointRotation(parentJointIndex, palmRotation, true); - applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()), false); + applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()), true, true); getJointRotation(parentJointIndex, palmRotation, true); // sort the finger indices by raw x, get the average direction @@ -178,7 +178,8 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin float directionLength = glm::length(direction); const unsigned int MIN_ROTATION_FINGERS = 3; if (directionLength > EPSILON && palm.getNumFingers() >= MIN_ROTATION_FINGERS) { - applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction), false); + applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction), + true, true); getJointRotation(parentJointIndex, palmRotation, true); } diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index f8de7210ea..36088dec70 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -997,9 +997,10 @@ float Model::getLimbLength(int jointIndex) const { return length; } -void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain) { +void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, bool propagate) { JointState& state = _jointStates[jointIndex]; - const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; + const FBXGeometry& geometry = _geometry->getFBXGeometry(); + const FBXJoint& joint = geometry.joints[jointIndex]; if (!constrain || (joint.rotationMin == glm::vec3(-PI, -PI, -PI) && joint.rotationMax == glm::vec3(PI, PI, PI))) { // no constraints @@ -1007,10 +1008,16 @@ void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool cons state.combinedRotation = delta * state.combinedRotation; return; } + glm::quat targetRotation = delta * state.combinedRotation; glm::quat newRotation = glm::quat(glm::clamp(safeEulerAngles(state.rotation * - glm::inverse(state.combinedRotation) * delta * state.combinedRotation), joint.rotationMin, joint.rotationMax)); + glm::inverse(state.combinedRotation) * targetRotation), joint.rotationMin, joint.rotationMax)); state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation; state.rotation = newRotation; + + if (propagate && targetRotation != state.combinedRotation && + joint.parentIndex != -1 && geometry.joints[joint.parentIndex].isFree) { + applyRotationDelta(joint.parentIndex, targetRotation * glm::inverse(state.combinedRotation), true, true); + } } const int BALL_SUBDIVISIONS = 10; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 65b79fffdd..b472e17b20 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -256,7 +256,7 @@ protected: /// first free ancestor. float getLimbLength(int jointIndex) const; - void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true); + void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true, bool propagate = false); private: From 743034c986fffd65bd564176239b3de019836367 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 18 Apr 2014 15:09:37 -0700 Subject: [PATCH 07/76] Need to transfer parent rotation to child. --- interface/src/renderer/Model.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 36088dec70..17d3dd783c 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1017,6 +1017,7 @@ void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool cons if (propagate && targetRotation != state.combinedRotation && joint.parentIndex != -1 && geometry.joints[joint.parentIndex].isFree) { applyRotationDelta(joint.parentIndex, targetRotation * glm::inverse(state.combinedRotation), true, true); + state.combinedRotation = _jointStates.at(joint.parentIndex).combinedRotation * state.rotation; } } From e2558bdac088908ed755fcdb3d3175932567d9a6 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 18 Apr 2014 17:16:20 -0700 Subject: [PATCH 08/76] Experimenting with tweaking the Euler angles so that z, rather than y, is in [-pi/2, pi/2]. --- interface/src/renderer/Model.cpp | 11 ++++++--- libraries/shared/src/SharedUtil.cpp | 38 ++++++++++++++++++++++++++--- 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 17d3dd783c..2ff8a0fee9 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -892,6 +892,11 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int last lastFreeIndex = freeLineage.last(); } + // now update the joint states from the top + for (int j = freeLineage.size() - 1; j >= 0; j--) { + updateJointState(freeLineage.at(j)); + } + // this is a cyclic coordinate descent algorithm: see // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d const int ITERATION_COUNT = 1; @@ -1009,13 +1014,13 @@ void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool cons return; } glm::quat targetRotation = delta * state.combinedRotation; - glm::quat newRotation = glm::quat(glm::clamp(safeEulerAngles(state.rotation * - glm::inverse(state.combinedRotation) * targetRotation), joint.rotationMin, joint.rotationMax)); + glm::vec3 eulers = safeEulerAngles(state.rotation * glm::inverse(state.combinedRotation) * targetRotation); + glm::quat newRotation = glm::quat(glm::clamp(eulers, joint.rotationMin, joint.rotationMax)); state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation; state.rotation = newRotation; if (propagate && targetRotation != state.combinedRotation && - joint.parentIndex != -1 && geometry.joints[joint.parentIndex].isFree) { + joint.parentIndex != -1 && geometry.joints.at(joint.parentIndex).isFree) { applyRotationDelta(joint.parentIndex, targetRotation * glm::inverse(state.combinedRotation), true, true); state.combinedRotation = _jointStates.at(joint.parentIndex).combinedRotation * state.rotation; } diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index f4e4b28f93..69381a07ae 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -640,27 +640,59 @@ void debug::checkDeadBeef(void* memoryVoid, int size) { // https://github.com/threerings/clyde/blob/master/src/main/java/com/threerings/math/Quaternion.java) glm::vec3 safeEulerAngles(const glm::quat& q) { float sy = 2.0f * (q.y * q.w - q.x * q.z); + glm::vec3 eulers; if (sy < 1.0f - EPSILON) { if (sy > -1.0f + EPSILON) { - return glm::vec3( + eulers = glm::vec3( atan2f(q.y * q.z + q.x * q.w, 0.5f - (q.x * q.x + q.y * q.y)), asinf(sy), atan2f(q.x * q.y + q.z * q.w, 0.5f - (q.y * q.y + q.z * q.z))); } else { // not a unique solution; x + z = atan2(-m21, m11) - return glm::vec3( + eulers = glm::vec3( 0.0f, - PI_OVER_TWO, atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z))); } } else { // not a unique solution; x - z = atan2(-m21, m11) - return glm::vec3( + eulers = glm::vec3( 0.0f, PI_OVER_TWO, -atan2f(q.x * q.w - q.y * q.z, 0.5f - (q.x * q.x + q.z * q.z))); } + + // adjust so that z, rather than y, is in [-pi/2, pi/2] + if (eulers.z < -PI_OVER_TWO) { + if (eulers.x < 0.0f) { + eulers.x += PI; + } else { + eulers.x -= PI; + } + eulers.y = -eulers.y; + if (eulers.y < 0.0f) { + eulers.y += PI; + } else { + eulers.y -= PI; + } + eulers.z += PI; + + } else if (eulers.z > PI_OVER_TWO) { + if (eulers.x < 0.0f) { + eulers.x += PI; + } else { + eulers.x -= PI; + } + eulers.y = -eulers.y; + if (eulers.y < 0.0f) { + eulers.y += PI; + } else { + eulers.y -= PI; + } + eulers.z -= PI; + } + return eulers; } // Helper function returns the positive angle (in radians) between two 3D vectors From 241df7a7675c83ab7fbbabaf6c9903ac398d667d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 10:27:20 -0700 Subject: [PATCH 09/76] Move AABox from octree lib to shared lib Stubbed out Shape vs Octree collisions --- libraries/octree/src/Octree.cpp | 58 ++++++++++++++++++++-- libraries/octree/src/Octree.h | 5 ++ libraries/octree/src/OctreeElement.cpp | 2 +- libraries/octree/src/OctreeElement.h | 3 +- libraries/octree/src/ViewFrustum.h | 2 +- libraries/{octree => shared}/src/AABox.cpp | 2 +- libraries/{octree => shared}/src/AABox.h | 2 +- libraries/shared/src/ShapeCollider.cpp | 5 ++ libraries/shared/src/ShapeCollider.h | 7 +++ libraries/voxels/src/VoxelTreeElement.h | 2 +- 10 files changed, 79 insertions(+), 9 deletions(-) rename libraries/{octree => shared}/src/AABox.cpp (99%) rename libraries/{octree => shared}/src/AABox.h (98%) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 696a65b4b5..a06b8a41bb 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -20,18 +20,20 @@ #include -#include "CoverageMap.h" #include -#include "OctalCode.h" +#include #include #include +#include +#include //#include "Tags.h" -#include "ViewFrustum.h" +#include "CoverageMap.h" #include "OctreeConstants.h" #include "OctreeElementBag.h" #include "Octree.h" +#include "ViewFrustum.h" float boundaryDistanceForRenderLevel(unsigned int renderLevel, float voxelSizeScale) { return voxelSizeScale / powf(2, renderLevel); @@ -676,6 +678,13 @@ public: bool found; }; +class ShapeArgs { +public: + const Shape* shape; + CollisionList& collisions; + bool found; +}; + bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) { CapsuleArgs* args = static_cast(extraData); @@ -697,6 +706,24 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) { return false; } +bool findShapeCollisionsOp(OctreeElement* node, void* extraData) { + const ShapeArgs* args = static_cast(extraData); + + // coarse check against bounds + AABox box = node->getAABox(); + box.scale(TREE_SCALE); + if (!box.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) { + return false; + } + if (!node->isLeaf()) { + return true; // recurse on children + } + if (node->hasContent()) { + return ShapeCollider::collideShapeWithBox(args->shape, box, args->collisions); + } + return false; +} + bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration, Octree::lockType lockType) { @@ -727,6 +754,31 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end return args.found; } +bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType lockType) { + + ShapeArgs args = { shape, + collisions, + false }; + + bool gotLock = false; + if (lockType == Octree::Lock) { + lockForRead(); + gotLock = true; + } else if (lockType == Octree::TryLock) { + gotLock = tryLockForRead(); + if (!gotLock) { + return args.found; // if we wanted to tryLock, and we couldn't then just bail... + } + } + + recurseTreeWithOperation(findShapeCollisionsOp, &args); + + if (gotLock) { + unlock(); + } + return args.found; +} + class GetElementEnclosingArgs { public: OctreeElement* element; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 839e61d1c2..4c47c0ce9f 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -21,6 +21,7 @@ class Octree; class OctreeElement; class OctreeElementBag; class OctreePacketData; +class Shape; #include "JurisdictionMap.h" @@ -30,6 +31,8 @@ class OctreePacketData; #include "OctreePacketData.h" #include "OctreeSceneStats.h" +#include + #include #include @@ -246,6 +249,8 @@ public: bool findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, float radius, glm::vec3& penetration, Octree::lockType lockType = Octree::TryLock); + bool findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType = Octree::TryLock); + OctreeElement* getElementEnclosingPoint(const glm::vec3& point, Octree::lockType lockType = Octree::TryLock); // Note: this assumes the fileFormat is the HIO individual voxels code files diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index e21148df5e..c951803247 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -15,11 +15,11 @@ #include +#include #include #include #include -#include "AABox.h" #include "OctalCode.h" #include "SharedUtil.h" #include "OctreeConstants.h" diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 682516cf0a..15d5063818 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -18,8 +18,9 @@ #include +#include #include -#include "AABox.h" + #include "ViewFrustum.h" #include "OctreeConstants.h" //#include "Octree.h" diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 5c9d7f06c2..43812827f5 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -17,7 +17,7 @@ #include #include -#include "AABox.h" +#include #include "Plane.h" #include "OctreeConstants.h" diff --git a/libraries/octree/src/AABox.cpp b/libraries/shared/src/AABox.cpp similarity index 99% rename from libraries/octree/src/AABox.cpp rename to libraries/shared/src/AABox.cpp index 51b31d4466..ed99a24d38 100644 --- a/libraries/octree/src/AABox.cpp +++ b/libraries/shared/src/AABox.cpp @@ -1,6 +1,6 @@ // // AABox.cpp -// libraries/octree/src +// libraries/shared/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/octree/src/AABox.h b/libraries/shared/src/AABox.h similarity index 98% rename from libraries/octree/src/AABox.h rename to libraries/shared/src/AABox.h index 1aa0849b70..6531db4250 100644 --- a/libraries/octree/src/AABox.h +++ b/libraries/shared/src/AABox.h @@ -1,6 +1,6 @@ // // AABox.h -// libraries/octree/src +// libraries/shared/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index c53c7fab7d..0eddc80c62 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -92,6 +92,11 @@ bool collideShapesCoarse(const QVector& shapesA, const QVectorgetPosition() - sphereA->getPosition(); float distanceSquared = glm::dot(BA, BA); diff --git a/libraries/shared/src/ShapeCollider.h b/libraries/shared/src/ShapeCollider.h index d554775e7b..a020050662 100644 --- a/libraries/shared/src/ShapeCollider.h +++ b/libraries/shared/src/ShapeCollider.h @@ -12,6 +12,7 @@ #ifndef hifi_ShapeCollider_h #define hifi_ShapeCollider_h +#include "AABox.h" #include "CapsuleShape.h" #include "CollisionInfo.h" #include "ListShape.h" @@ -33,6 +34,12 @@ namespace ShapeCollider { /// \return true if any shapes collide bool collideShapesCoarse(const QVector& shapesA, const QVector& shapesB, CollisionInfo& collision); + /// \param shapeA a pointer to a shape + /// \param boxB an axis aligned box + /// \param collisions[out] average collision details + /// \return true if shapeA collides with boxB + bool collideShapeWithBox(const Shape* shapeA, const AABox& boxB, CollisionList& collisions); + /// \param sphereA pointer to first shape /// \param sphereB pointer to second shape /// \param[out] collisions where to append collision details diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index 140744afb0..8733987df4 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -18,10 +18,10 @@ #include +#include #include #include -#include "AABox.h" #include "ViewFrustum.h" #include "VoxelConstants.h" From 06784aa960b46612dceed11a13a2398666012600 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 14:07:40 -0700 Subject: [PATCH 10/76] move AABox back to octree lib Fleshing out ShapeCollider::collideShapeWithAACube() --- libraries/{shared => octree}/src/AABox.cpp | 0 libraries/{shared => octree}/src/AABox.h | 0 libraries/octree/src/Octree.cpp | 8 +-- libraries/octree/src/OctreeElement.cpp | 4 +- libraries/octree/src/OctreeElement.h | 2 +- libraries/octree/src/ViewFrustum.h | 3 +- libraries/shared/src/ShapeCollider.cpp | 80 +++++++++++++++++++++- libraries/shared/src/ShapeCollider.h | 22 ++++-- 8 files changed, 104 insertions(+), 15 deletions(-) rename libraries/{shared => octree}/src/AABox.cpp (100%) rename libraries/{shared => octree}/src/AABox.h (100%) diff --git a/libraries/shared/src/AABox.cpp b/libraries/octree/src/AABox.cpp similarity index 100% rename from libraries/shared/src/AABox.cpp rename to libraries/octree/src/AABox.cpp diff --git a/libraries/shared/src/AABox.h b/libraries/octree/src/AABox.h similarity index 100% rename from libraries/shared/src/AABox.h rename to libraries/octree/src/AABox.h diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index a06b8a41bb..83b84b3c50 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -710,16 +710,16 @@ bool findShapeCollisionsOp(OctreeElement* node, void* extraData) { const ShapeArgs* args = static_cast(extraData); // coarse check against bounds - AABox box = node->getAABox(); - box.scale(TREE_SCALE); - if (!box.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) { + AABox cube = node->getAABox(); + cube.scale(TREE_SCALE); + if (!cube.expandedContains(args->shape->getPosition(), args->shape->getBoundingRadius())) { return false; } if (!node->isLeaf()) { return true; // recurse on children } if (node->hasContent()) { - return ShapeCollider::collideShapeWithBox(args->shape, box, args->collisions); + return ShapeCollider::collideShapeWithAACube(args->shape, cube.calcCenter(), cube.getScale(), args->collisions); } return false; } diff --git a/libraries/octree/src/OctreeElement.cpp b/libraries/octree/src/OctreeElement.cpp index c951803247..7ca15eddb5 100644 --- a/libraries/octree/src/OctreeElement.cpp +++ b/libraries/octree/src/OctreeElement.cpp @@ -15,16 +15,16 @@ #include -#include #include #include #include +#include "AABox.h" #include "OctalCode.h" -#include "SharedUtil.h" #include "OctreeConstants.h" #include "OctreeElement.h" #include "Octree.h" +#include "SharedUtil.h" quint64 OctreeElement::_voxelMemoryUsage = 0; quint64 OctreeElement::_octcodeMemoryUsage = 0; diff --git a/libraries/octree/src/OctreeElement.h b/libraries/octree/src/OctreeElement.h index 15d5063818..c5eec1c9e2 100644 --- a/libraries/octree/src/OctreeElement.h +++ b/libraries/octree/src/OctreeElement.h @@ -18,9 +18,9 @@ #include -#include #include +#include "AABox.h" #include "ViewFrustum.h" #include "OctreeConstants.h" //#include "Octree.h" diff --git a/libraries/octree/src/ViewFrustum.h b/libraries/octree/src/ViewFrustum.h index 43812827f5..acd5c639f7 100644 --- a/libraries/octree/src/ViewFrustum.h +++ b/libraries/octree/src/ViewFrustum.h @@ -17,9 +17,8 @@ #include #include -#include +#include "AABox.h" #include "Plane.h" - #include "OctreeConstants.h" #include "OctreeProjectedPolygon.h" diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 0eddc80c62..1b49caab22 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -92,8 +92,26 @@ bool collideShapesCoarse(const QVector& shapesA, const QVectorgetType(); + if (typeA == Shape::SPHERE_SHAPE) { + return sphereAACube(static_cast(shapeA), cubeCenter, cubeSide, collisions); + } else if (typeA == Shape::CAPSULE_SHAPE) { + return capsuleAACube(static_cast(shapeA), cubeCenter, cubeSide, collisions); + } else if (typeA == Shape::LIST_SHAPE) { + const ListShape* listA = static_cast(shapeA); + bool touching = false; + for (int i = 0; i < listA->size() && !collisions.isFull(); ++i) { + const Shape* subShape = listA->getSubShape(i); + int subType = subShape->getType(); + if (subType == Shape::SPHERE_SHAPE) { + touching = sphereAACube(static_cast(subShape), cubeCenter, cubeSide, collisions) || touching; + } else if (subType == Shape::CAPSULE_SHAPE) { + touching = capsuleAACube(static_cast(subShape), cubeCenter, cubeSide, collisions) || touching; + } + } + return touching; + } return false; } @@ -572,4 +590,62 @@ bool listList(const ListShape* listA, const ListShape* listB, CollisionList& col return touching; } +// helper function +bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { + glm::vec3 BA = cubeCenter - sphereCenter; + float distance = glm::length(BA); + if (distance > EPSILON) { + BA /= distance; // BA is now normalized + // compute the nearest point on sphere + glm::vec3 surfaceA = sphereCenter + sphereRadius * BA; + // compute the nearest point on cube + float maxBA = glm::max(glm::max(fabs(BA.x), fabs(BA.y)), fabs(BA.z)); + glm::vec3 surfaceB = cubeCenter - (0.5f * cubeSide / maxBA) * BA; + // collision happens when "vector to surfaceB from surfaceA" dots with BA to produce a positive value + glm::vec3 surfaceBA = surfaceB - surfaceA; + if (glm::dot(surfaceBA, BA) > 0.f) { + CollisionInfo* collision = collisions.getNewCollision(); + if (collision) { + collision->_penetration = surfaceBA; + // contactPoint is on surface of A + collision->_contactPoint = surfaceA; + return true; + } + } + } else if (sphereRadius + 0.5f * cubeSide > distance) { + // NOTE: for cocentric approximation we collide sphere and cube as two spheres which means + // this algorithm will probably be wrong when both sphere and cube are very small (both ~EPSILON) + CollisionInfo* collision = collisions.getNewCollision(); + if (collision) { + // the penetration and contactPoint are undefined, so we pick a penetration direction (-yAxis) + collision->_penetration = (sphereRadius + 0.5f * cubeSide) * glm::vec3(0.0f, -1.0f, 0.0f); + // contactPoint is on surface of A + collision->_contactPoint = sphereCenter + collision->_penetration; + return true; + } + } + return false; +} + +bool sphereAACube(const SphereShape* sphereA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { + return sphereAACube(sphereA->getPosition(), sphereA->getRadius(), cubeCenter, cubeSide, collisions); +} + +bool capsuleAACube(const CapsuleShape* capsuleA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions) { + // find nerest approach of capsule line segment to cube + glm::vec3 capsuleAxis; + capsuleA->computeNormalizedAxis(capsuleAxis); + float offset = glm::dot(cubeCenter - capsuleA->getPosition(), capsuleAxis); + float halfHeight = capsuleA->getHalfHeight(); + if (offset > halfHeight) { + offset = halfHeight; + } else if (offset < -halfHeight) { + offset = -halfHeight; + } + glm::vec3 nearestApproach = capsuleA->getPosition() + offset * capsuleAxis; + // collide nearest approach like a sphere at that point + return sphereAACube(nearestApproach, capsuleA->getRadius(), cubeCenter, cubeSide, collisions); +} + + } // namespace ShapeCollider diff --git a/libraries/shared/src/ShapeCollider.h b/libraries/shared/src/ShapeCollider.h index a020050662..9e83e31571 100644 --- a/libraries/shared/src/ShapeCollider.h +++ b/libraries/shared/src/ShapeCollider.h @@ -12,7 +12,6 @@ #ifndef hifi_ShapeCollider_h #define hifi_ShapeCollider_h -#include "AABox.h" #include "CapsuleShape.h" #include "CollisionInfo.h" #include "ListShape.h" @@ -35,10 +34,11 @@ namespace ShapeCollider { bool collideShapesCoarse(const QVector& shapesA, const QVector& shapesB, CollisionInfo& collision); /// \param shapeA a pointer to a shape - /// \param boxB an axis aligned box + /// \param cubeCenter center of cube + /// \param cubeSide lenght of side of cube /// \param collisions[out] average collision details - /// \return true if shapeA collides with boxB - bool collideShapeWithBox(const Shape* shapeA, const AABox& boxB, CollisionList& collisions); + /// \return true if shapeA collides with axis aligned cube + bool collideShapeWithAACube(const Shape* shapeA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); /// \param sphereA pointer to first shape /// \param sphereB pointer to second shape @@ -136,6 +136,20 @@ namespace ShapeCollider { /// \return true if shapes collide bool listList(const ListShape* listA, const ListShape* listB, CollisionList& collisions); + /// \param sphereA pointer to sphere + /// \param cubeCenter center of cube + /// \param cubeSide lenght of side of cube + /// \param[out] collisions where to append collision details + /// \return true if sphereA collides with axis aligned cube + bool sphereAACube(const SphereShape* sphereA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); + + /// \param capsuleA pointer to capsule + /// \param cubeCenter center of cube + /// \param cubeSide lenght of side of cube + /// \param[out] collisions where to append collision details + /// \return true if capsuleA collides with axis aligned cube + bool capsuleAACube(const CapsuleShape* capsuleA, const glm::vec3& cubeCenter, float cubeSide, CollisionList& collisions); + } // namespace ShapeCollider #endif // hifi_ShapeCollider_h From f7f30e118c4f1b36178a3e0d4f4bd603f4519221 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 21 Apr 2014 15:17:11 -0700 Subject: [PATCH 11/76] More gettimeofday cleanup --- interface/src/Application.cpp | 27 ++++----- interface/src/Application.h | 8 +-- interface/src/Util.cpp | 47 +++++---------- interface/src/Util.h | 2 - interface/src/main.cpp | 6 +- interface/src/starfield/Controller.cpp | 10 ++-- interface/src/starfield/Generator.cpp | 9 ++- interface/src/ui/BandwidthMeter.cpp | 13 ++--- interface/src/ui/BandwidthMeter.h | 4 +- libraries/script-engine/src/ScriptEngine.cpp | 6 +- libraries/shared/src/SharedUtil.cpp | 4 -- libraries/shared/src/SharedUtil.h | 1 - libraries/shared/src/Systime.cpp | 61 -------------------- libraries/shared/src/Systime.h | 27 --------- 14 files changed, 57 insertions(+), 168 deletions(-) delete mode 100644 libraries/shared/src/Systime.cpp delete mode 100644 libraries/shared/src/Systime.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index cd07f21300..92c63dacf3 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -134,7 +134,7 @@ QString& Application::resourcesPath() { return staticResourcePath; } -Application::Application(int& argc, char** argv, timeval &startup_time) : +Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : QApplication(argc, argv), _window(new QMainWindow(desktop())), _glWidget(new GLCanvas()), @@ -507,7 +507,7 @@ void Application::initializeGL() { _idleLoopStdev.reset(); if (_justStarted) { - float startupTime = (usecTimestampNow() - usecTimestamp(&_applicationStartupTime)) / 1000000.0; + float startupTime = _applicationStartupTime.elapsed() / 1000.0; _justStarted = false; qDebug("Startup time: %4.2f seconds.", startupTime); const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time"; @@ -1273,21 +1273,21 @@ void Application::sendPingPackets() { // Every second, check the frame rates and other stuff void Application::timer() { - gettimeofday(&_timerEnd, NULL); - if (Menu::getInstance()->isOptionChecked(MenuOption::TestPing)) { sendPingPackets(); } + + float diffTime = (float)_timerStart.nsecsElapsed() / 1000000000.0; - _fps = (float)_frameCount / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); + _fps = (float)_frameCount / diffTime; - _packetsPerSecond = (float) _datagramProcessor.getPacketCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); - _bytesPerSecond = (float) _datagramProcessor.getByteCount() / ((float)diffclock(&_timerStart, &_timerEnd) / 1000.f); + _packetsPerSecond = (float) _datagramProcessor.getPacketCount() / diffTime; + _bytesPerSecond = (float) _datagramProcessor.getByteCount() / diffTime; _frameCount = 0; _datagramProcessor.resetCounters(); - gettimeofday(&_timerStart, NULL); + _timerStart.start(); // ask the node list to check in with the domain server NodeList::getInstance()->sendDomainServerCheckIn(); @@ -1300,13 +1300,11 @@ void Application::idle() { bool showWarnings = getLogger()->extraDebugging(); PerformanceWarning warn(showWarnings, "Application::idle()"); - timeval check; - gettimeofday(&check, NULL); - // Only run simulation code if more than IDLE_SIMULATE_MSECS have passed since last time we ran - double timeSinceLastUpdate = diffclock(&_lastTimeUpdated, &check); + double timeSinceLastUpdate = (double)_lastTimeUpdated.nsecsElapsed() / 1000000.0; if (timeSinceLastUpdate > IDLE_SIMULATE_MSECS) { + _lastTimeUpdated.start(); { PerformanceWarning warn(showWarnings, "Application::idle()... update()"); const float BIGGEST_DELTA_TIME_SECS = 0.25f; @@ -1318,7 +1316,6 @@ void Application::idle() { } { PerformanceWarning warn(showWarnings, "Application::idle()... rest of it"); - _lastTimeUpdated = check; _idleLoopStdev.addValue(timeSinceLastUpdate); // Record standard deviation and reset counter if needed @@ -1634,8 +1631,8 @@ void Application::init() { Qt::QueuedConnection); } - gettimeofday(&_timerStart, NULL); - gettimeofday(&_lastTimeUpdated, NULL); + _timerStart.start(); + _lastTimeUpdated.start(); Menu::getInstance()->loadSettings(); if (Menu::getInstance()->getAudioJitterBufferSamples() != 0) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 9d609ad5f5..36758a26db 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -117,7 +117,7 @@ public: static Application* getInstance() { return static_cast(QCoreApplication::instance()); } static QString& resourcesPath(); - Application(int& argc, char** argv, timeval &startup_time); + Application(int& argc, char** argv, QElapsedTimer &startup_time); ~Application(); void restoreSizeAndPosition(); @@ -391,9 +391,9 @@ private: int _frameCount; float _fps; - timeval _applicationStartupTime; - timeval _timerStart, _timerEnd; - timeval _lastTimeUpdated; + QElapsedTimer _applicationStartupTime; + QElapsedTimer _timerStart; + QElapsedTimer _lastTimeUpdated; bool _justStarted; Stars _stars; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 1dae3a4fd6..9dfe9d8002 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -172,14 +172,6 @@ void renderWorldBox() { } -double diffclock(timeval *clock1,timeval *clock2) -{ - double diffms = (clock2->tv_sec - clock1->tv_sec) * 1000.0; - diffms += (clock2->tv_usec - clock1->tv_usec) / 1000.0; // us to ms - - return diffms; -} - // Return a random vector of average length 1 const glm::vec3 randVector() { return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.f; @@ -411,68 +403,61 @@ void runTimingTests() { int iResults[numTests]; float fTest = 1.0; float fResults[numTests]; - timeval startTime, endTime; + QElapsedTimer startTime; + startTime.start(); float elapsedMsecs; - gettimeofday(&startTime, NULL); - for (int i = 1; i < numTests; i++) { - gettimeofday(&endTime, NULL); - } - elapsedMsecs = diffclock(&startTime, &endTime); - qDebug("gettimeofday() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("QElapsedTimer::nsecElapsed() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); // Random number generation - gettimeofday(&startTime, NULL); + startTime.start(); for (int i = 1; i < numTests; i++) { iResults[i] = rand(); } - gettimeofday(&endTime, NULL); - elapsedMsecs = diffclock(&startTime, &endTime); + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedMsecs / (float) numTests, iResults[0]); // Random number generation using randFloat() - gettimeofday(&startTime, NULL); + startTime.start(); for (int i = 1; i < numTests; i++) { fResults[i] = randFloat(); } - gettimeofday(&endTime, NULL); - elapsedMsecs = diffclock(&startTime, &endTime); + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedMsecs / (float) numTests, fResults[0]); // PowF function fTest = 1145323.2342f; - gettimeofday(&startTime, NULL); + startTime.start(); for (int i = 1; i < numTests; i++) { fTest = powf(fTest, 0.5f); } - gettimeofday(&endTime, NULL); - elapsedMsecs = diffclock(&startTime, &endTime); + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; qDebug("powf(f, 0.5) usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); // Vector Math float distance; glm::vec3 pointA(randVector()), pointB(randVector()); - gettimeofday(&startTime, NULL); + startTime.start(); for (int i = 1; i < numTests; i++) { //glm::vec3 temp = pointA - pointB; //float distanceSquared = glm::dot(temp, temp); distance = glm::distance(pointA, pointB); } - gettimeofday(&endTime, NULL); - elapsedMsecs = diffclock(&startTime, &endTime); + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; qDebug("vector math usecs: %f [%f msecs total for %d tests], last result:%f", 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests, distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); float result; - - gettimeofday(&startTime, NULL); + + startTime.start(); for (int i = 1; i < numTests; i++) { glm::vec3 temp = vecA-vecB; result = glm::dot(temp,temp); } - gettimeofday(&endTime, NULL); - elapsedMsecs = diffclock(&startTime, &endTime); + elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedMsecs / (float) numTests, result); } diff --git a/interface/src/Util.h b/interface/src/Util.h index 4bd1ed604c..dee0f864b4 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -44,8 +44,6 @@ void drawVector(glm::vec3* vector); void printVector(glm::vec3 vec); -double diffclock(timeval *clock1,timeval *clock2); - void renderCollisionOverlay(int width, int height, float magnitude, float red = 0, float blue = 0, float green = 0); void renderOrientationDirections( glm::vec3 position, const glm::quat& orientation, float size ); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 40e2a9ab27..2bb0633f24 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -16,8 +16,8 @@ #include int main(int argc, const char * argv[]) { - timeval startup_time; - gettimeofday(&startup_time, NULL); + QElapsedTimer startupTime; + startupTime.start(); // Debug option to demonstrate that the client's local time does not // need to be in sync with any other network node. This forces clock @@ -33,7 +33,7 @@ int main(int argc, const char * argv[]) { int exitCode; { QSettings::setDefaultFormat(QSettings::IniFormat); - Application app(argc, const_cast(argv), startup_time); + Application app(argc, const_cast(argv), startupTime); QTranslator translator; translator.load("interface_en"); diff --git a/interface/src/starfield/Controller.cpp b/interface/src/starfield/Controller.cpp index 771029c689..2476c33d45 100755 --- a/interface/src/starfield/Controller.cpp +++ b/interface/src/starfield/Controller.cpp @@ -13,20 +13,22 @@ #include #endif +#include + #include "starfield/Controller.h" using namespace starfield; bool Controller::computeStars(unsigned numStars, unsigned seed) { - timeval startTime; - gettimeofday(&startTime, NULL); + QElapsedTimer startTime; + startTime.start(); Generator::computeStarPositions(_inputSequence, numStars, seed); this->retile(numStars, _tileResolution); - qDebug() << "Total time to retile and generate stars: " - << ((usecTimestampNow() - usecTimestamp(&startTime)) / 1000) << "msec"; + double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms + qDebug() << "Total time to retile and generate stars: " << timeDiff << "msec"; return true; } diff --git a/interface/src/starfield/Generator.cpp b/interface/src/starfield/Generator.cpp index b18e1834be..869abc90a5 100644 --- a/interface/src/starfield/Generator.cpp +++ b/interface/src/starfield/Generator.cpp @@ -13,6 +13,8 @@ #include #endif +#include + #include "starfield/Generator.h" using namespace starfield; @@ -24,8 +26,8 @@ void Generator::computeStarPositions(InputVertices& destination, unsigned limit, InputVertices* vertices = & destination; //_limit = limit; - timeval startTime; - gettimeofday(&startTime, NULL); + QElapsedTimer startTime; + startTime.start(); srand(seed); @@ -70,7 +72,8 @@ void Generator::computeStarPositions(InputVertices& destination, unsigned limit, vertices->push_back(InputVertex(azimuth, altitude, computeStarColor(STAR_COLORIZATION))); } - qDebug() << "Total time to generate stars: " << ((usecTimestampNow() - usecTimestamp(&startTime)) / 1000) << " msec"; + double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms + qDebug() << "Total time to generate stars: " << timeDiff << " msec"; } // computeStarColor diff --git a/interface/src/ui/BandwidthMeter.cpp b/interface/src/ui/BandwidthMeter.cpp index 3ed66c53e1..0f41a1a5cf 100644 --- a/interface/src/ui/BandwidthMeter.cpp +++ b/interface/src/ui/BandwidthMeter.cpp @@ -62,26 +62,21 @@ BandwidthMeter::~BandwidthMeter() { free(_channels); } -BandwidthMeter::Stream::Stream(float msToAverage) : - _value(0.0f), - _msToAverage(msToAverage) { - - gettimeofday(& _prevTime, NULL); +BandwidthMeter::Stream::Stream(float msToAverage) : _value(0.0f), _msToAverage(msToAverage) { + _prevTime.start(); } void BandwidthMeter::Stream::updateValue(double amount) { // Determine elapsed time - timeval now; - gettimeofday(& now, NULL); - double dt = diffclock(& _prevTime, & now); + double dt = (double)_prevTime.nsecsElapsed() / 1000000.0; // ns to ms // Ignore this value when timer imprecision yields dt = 0 if (dt == 0.0) { return; } - memcpy(& _prevTime, & now, sizeof(timeval)); + _prevTime.start(); // Compute approximate average _value = glm::mix(_value, amount / dt, diff --git a/interface/src/ui/BandwidthMeter.h b/interface/src/ui/BandwidthMeter.h index 6838f28c70..6cf7e9ea63 100644 --- a/interface/src/ui/BandwidthMeter.h +++ b/interface/src/ui/BandwidthMeter.h @@ -16,6 +16,8 @@ #include #endif +#include + #include #include "ui/TextRenderer.h" @@ -59,7 +61,7 @@ public: private: double _value; // Current value. double _msToAverage; // Milliseconds to average. - timeval _prevTime; // Time of last feed. + QElapsedTimer _prevTime; // Time of last feed. }; // Data model accessors diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 684c55fbb0..dcf64dfe2c 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -273,8 +273,8 @@ void ScriptEngine::run() { qDebug() << "Uncaught exception at line" << line << ":" << result.toString(); } - timeval startTime; - gettimeofday(&startTime, NULL); + QElapsedTimer startTime; + startTime.start(); int thisFrame = 0; @@ -283,7 +283,7 @@ void ScriptEngine::run() { qint64 lastUpdate = usecTimestampNow(); while (!_isFinished) { - int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - usecTimestampNow(); + int usecToSleep = (thisFrame++ * SCRIPT_DATA_CALLBACK_USECS) - startTime.nsecsElapsed() / 1000; // nsec to usec if (usecToSleep > 0) { usleep(usecToSleep); } diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index f4e4b28f93..dca9426cb4 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -24,10 +24,6 @@ #include "OctalCode.h" #include "SharedUtil.h" -quint64 usecTimestamp(const timeval *time) { - return (time->tv_sec * 1000000 + time->tv_usec); -} - int usecTimestampNowAdjust = 0; void usecTimestampNowForceClockSkew(int clockSkew) { ::usecTimestampNowAdjust = clockSkew; diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index a8403d617c..87647a9e73 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -66,7 +66,6 @@ static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; const int BITS_IN_BYTE = 8; -quint64 usecTimestamp(const timeval *time); quint64 usecTimestampNow(); void usecTimestampNowForceClockSkew(int clockSkew); diff --git a/libraries/shared/src/Systime.cpp b/libraries/shared/src/Systime.cpp deleted file mode 100644 index ab32821a0f..0000000000 --- a/libraries/shared/src/Systime.cpp +++ /dev/null @@ -1,61 +0,0 @@ -// -// Systime.cpp -// libraries/shared/src -// -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifdef WIN32 - -#include "Systime.h" - -/** - * gettimeofday - * Implementation according to: - * The Open Group Base Specifications Issue 6 - * IEEE Std 1003.1, 2004 Edition - */ - -/** - * THIS SOFTWARE IS NOT COPYRIGHTED - * - * This source code is offered for use in the public domain. You may - * use, modify or distribute it freely. - * - * This code is distributed in the hope that it will be useful but - * WITHOUT ANY WARRANTY. ALL WARRANTIES, EXPRESS OR IMPLIED ARE HEREBY - * DISCLAIMED. This includes but is not limited to warranties of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * - * Contributed by: - * Danny Smith - */ - -#define WIN32_LEAN_AND_MEAN -#include - -/** Offset between 1/1/1601 and 1/1/1970 in 100 nanosec units */ -#define _W32_FT_OFFSET (116444736000000000ULL) - -int gettimeofday(timeval* p_tv, timezone* p_tz) { - - union { - unsigned long long ns100; /**time since 1 Jan 1601 in 100ns units */ - FILETIME ft; - } _now; - - if (p_tv) { - GetSystemTimeAsFileTime (&_now.ft); - p_tv->tv_usec=(long)((_now.ns100 / 10ULL) % 1000000ULL ); - p_tv->tv_sec= (long)((_now.ns100 - _W32_FT_OFFSET) / 10000000ULL); - } - - /** Always return 0 as per Open Group Base Specifications Issue 6. - Do not set errno on error. */ - return 0; -} - -#endif \ No newline at end of file diff --git a/libraries/shared/src/Systime.h b/libraries/shared/src/Systime.h deleted file mode 100644 index 3098f09ecd..0000000000 --- a/libraries/shared/src/Systime.h +++ /dev/null @@ -1,27 +0,0 @@ -// -// Systime.h -// libraries/shared/src -// -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#ifndef hifi_Systime_h -#define hifi_Systime_h - -#ifdef WIN32 - -#include - -struct timezone { - int tz_minuteswest; /* minutes west of Greenwich */ - int tz_dsttime; /* type of dst correction */ -}; - -int gettimeofday(struct timeval* p_tv, struct timezone* p_tz); - -#endif - -#endif // hifi_Systime_h \ No newline at end of file From 0479aaba4651594b760979f0ed460665234d7f1e Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 21 Apr 2014 15:26:43 -0700 Subject: [PATCH 12/76] Some gettimeofday removal fixes --- interface/src/Application.cpp | 2 +- interface/src/Util.cpp | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 92c63dacf3..b13013cbe2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -507,7 +507,7 @@ void Application::initializeGL() { _idleLoopStdev.reset(); if (_justStarted) { - float startupTime = _applicationStartupTime.elapsed() / 1000.0; + float startupTime = (float)_applicationStartupTime.elapsed() / 1000.0; _justStarted = false; qDebug("Startup time: %4.2f seconds.", startupTime); const char LOGSTASH_INTERFACE_START_TIME_KEY[] = "interface-start-time"; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 9dfe9d8002..7913ff2f47 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -405,26 +405,26 @@ void runTimingTests() { float fResults[numTests]; QElapsedTimer startTime; startTime.start(); - float elapsedMsecs; + float elapsedUsecs; - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("QElapsedTimer::nsecElapsed() usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("QElapsedTimer::nsecElapsed() usecs: %f", 1000.0f * elapsedUsecs / (float) numTests); // Random number generation startTime.start(); for (int i = 1; i < numTests; i++) { iResults[i] = rand(); } - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedMsecs / (float) numTests, iResults[0]); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedUsecs / (float) numTests, iResults[0]); // Random number generation using randFloat() startTime.start(); for (int i = 1; i < numTests; i++) { fResults[i] = randFloat(); } - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedMsecs / (float) numTests, fResults[0]); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedUsecs / (float) numTests, fResults[0]); // PowF function fTest = 1145323.2342f; @@ -432,8 +432,8 @@ void runTimingTests() { for (int i = 1; i < numTests; i++) { fTest = powf(fTest, 0.5f); } - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("powf(f, 0.5) usecs: %f", 1000.0f * elapsedMsecs / (float) numTests); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("powf(f, 0.5) usecs: %f", 1000.0f * elapsedUsecs / (float) numTests); // Vector Math float distance; @@ -444,9 +444,9 @@ void runTimingTests() { //float distanceSquared = glm::dot(temp, temp); distance = glm::distance(pointA, pointB); } - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("vector math usecs: %f [%f msecs total for %d tests], last result:%f", - 1000.0f * elapsedMsecs / (float) numTests, elapsedMsecs, numTests, distance); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("vector math usecs: %f [%f usecs total for %d tests], last result:%f", + 1000.0f * elapsedUsecs / (float) numTests, elapsedUsecs, numTests, distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); @@ -457,8 +457,8 @@ void runTimingTests() { glm::vec3 temp = vecA-vecB; result = glm::dot(temp,temp); } - elapsedMsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedMsecs / (float) numTests, result); + elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedUsecs / (float) numTests, result); } float loadSetting(QSettings* settings, const char* name, float defaultValue) { From be2db49e08be2fa49faed4d0f62b3106b226d4cd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 21 Apr 2014 16:44:21 -0700 Subject: [PATCH 13/76] Last touch to removing gettimeofday --- libraries/shared/src/SharedUtil.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index dca9426cb4..a13772d862 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -20,6 +20,7 @@ #endif #include +#include #include "OctalCode.h" #include "SharedUtil.h" @@ -30,9 +31,8 @@ void usecTimestampNowForceClockSkew(int clockSkew) { } quint64 usecTimestampNow() { - timeval now; - gettimeofday(&now, NULL); - return (now.tv_sec * 1000000 + now.tv_usec) + ::usecTimestampNowAdjust; + qint64 msecSinceEpoch = QDateTime::currentMSecsSinceEpoch(); + return msecSinceEpoch * 1000 + ::usecTimestampNowAdjust; } float randFloat() { From fd20686f0f854a33d897c5973535fd57c2e1fd60 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Mon, 21 Apr 2014 17:23:06 -0700 Subject: [PATCH 14/76] Removed Systime.h includes --- assignment-client/src/audio/AudioMixer.cpp | 2 -- interface/src/Application.cpp | 4 ---- interface/src/Audio.h | 4 ---- interface/src/Util.h | 6 ------ interface/src/devices/OculusManager.cpp | 4 ---- interface/src/devices/TV3DManager.cpp | 5 ----- interface/src/starfield/Controller.cpp | 4 ---- interface/src/starfield/Generator.cpp | 4 ---- interface/src/ui/BandwidthMeter.h | 4 ---- libraries/networking/src/Assignment.h | 6 ------ libraries/shared/src/PerfStat.h | 6 ------ libraries/shared/src/SharedUtil.h | 6 ------ 12 files changed, 55 deletions(-) diff --git a/assignment-client/src/audio/AudioMixer.cpp b/assignment-client/src/audio/AudioMixer.cpp index 65d09f1b00..5fd9efedd7 100644 --- a/assignment-client/src/audio/AudioMixer.cpp +++ b/assignment-client/src/audio/AudioMixer.cpp @@ -21,12 +21,10 @@ #include #ifdef _WIN32 -#include "Systime.h" #include #else #include #include -#include #include #endif //_WIN32 diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index b13013cbe2..1e3d3a2259 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -9,10 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef WIN32 -#include -#endif - #include #include diff --git a/interface/src/Audio.h b/interface/src/Audio.h index f8315b1aab..7ad1ddd926 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -12,10 +12,6 @@ #ifndef hifi_Audio_h #define hifi_Audio_h -#ifdef _WIN32 -#include -#endif - #include #include diff --git a/interface/src/Util.h b/interface/src/Util.h index dee0f864b4..02cfd99f9a 100644 --- a/interface/src/Util.h +++ b/interface/src/Util.h @@ -12,12 +12,6 @@ #ifndef hifi_Util_h #define hifi_Util_h -#ifdef _WIN32 -#include "Systime.h" -#else -#include -#endif - #include #include #include diff --git a/interface/src/devices/OculusManager.cpp b/interface/src/devices/OculusManager.cpp index d3da8fe7c3..854b19236d 100644 --- a/interface/src/devices/OculusManager.cpp +++ b/interface/src/devices/OculusManager.cpp @@ -11,10 +11,6 @@ #include "InterfaceConfig.h" -#ifdef WIN32 -#include -#endif - #include #include diff --git a/interface/src/devices/TV3DManager.cpp b/interface/src/devices/TV3DManager.cpp index fcbef0385c..b5cc28b07f 100644 --- a/interface/src/devices/TV3DManager.cpp +++ b/interface/src/devices/TV3DManager.cpp @@ -15,11 +15,6 @@ #include - -#ifdef WIN32 -#include -#endif - #include "Application.h" #include "TV3DManager.h" diff --git a/interface/src/starfield/Controller.cpp b/interface/src/starfield/Controller.cpp index 2476c33d45..e68243752c 100755 --- a/interface/src/starfield/Controller.cpp +++ b/interface/src/starfield/Controller.cpp @@ -9,10 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef _WIN32 -#include -#endif - #include #include "starfield/Controller.h" diff --git a/interface/src/starfield/Generator.cpp b/interface/src/starfield/Generator.cpp index 869abc90a5..d9773e4452 100644 --- a/interface/src/starfield/Generator.cpp +++ b/interface/src/starfield/Generator.cpp @@ -9,10 +9,6 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // -#ifdef _WIN32 -#include -#endif - #include #include "starfield/Generator.h" diff --git a/interface/src/ui/BandwidthMeter.h b/interface/src/ui/BandwidthMeter.h index 6cf7e9ea63..c6a28a21c3 100644 --- a/interface/src/ui/BandwidthMeter.h +++ b/interface/src/ui/BandwidthMeter.h @@ -12,10 +12,6 @@ #ifndef hifi_BandwidthMeter_h #define hifi_BandwidthMeter_h -#ifdef _WIN32 -#include -#endif - #include #include diff --git a/libraries/networking/src/Assignment.h b/libraries/networking/src/Assignment.h index 041121f760..f0f7e8db1a 100644 --- a/libraries/networking/src/Assignment.h +++ b/libraries/networking/src/Assignment.h @@ -12,12 +12,6 @@ #ifndef hifi_Assignment_h #define hifi_Assignment_h -#ifdef _WIN32 -#include "Systime.h" -#else -#include -#endif - #include #include "NodeList.h" diff --git a/libraries/shared/src/PerfStat.h b/libraries/shared/src/PerfStat.h index 478c9afead..22cf14f207 100644 --- a/libraries/shared/src/PerfStat.h +++ b/libraries/shared/src/PerfStat.h @@ -18,12 +18,6 @@ #include #include "SharedUtil.h" -#ifdef _WIN32 -#include "Systime.h" -#else -#include -#endif - #include #include #include diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 87647a9e73..4a3fe2a129 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -24,12 +24,6 @@ #include -#ifdef _WIN32 -#include "Systime.h" -#else -#include -#endif - const int BYTES_PER_COLOR = 3; const int BYTES_PER_FLAGS = 1; typedef unsigned char rgbColor[BYTES_PER_COLOR]; From 8d6fa8f90471a5cc60ea444e52c1e03e2614d562 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 18:19:59 -0700 Subject: [PATCH 15/76] fix sphere-vs-axis-aligned-cube logic --- libraries/shared/src/ShapeCollider.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 1b49caab22..c0de3cb90b 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -15,6 +15,7 @@ #include "GeometryUtil.h" #include "ShapeCollider.h" +#include "StreamUtils.h" // NOTE: // @@ -601,9 +602,9 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: // compute the nearest point on cube float maxBA = glm::max(glm::max(fabs(BA.x), fabs(BA.y)), fabs(BA.z)); glm::vec3 surfaceB = cubeCenter - (0.5f * cubeSide / maxBA) * BA; - // collision happens when "vector to surfaceB from surfaceA" dots with BA to produce a positive value + // collision happens when "vector to surfaceB from surfaceA" dots with BA to produce a negative value glm::vec3 surfaceBA = surfaceB - surfaceA; - if (glm::dot(surfaceBA, BA) > 0.f) { + if (glm::dot(surfaceBA, BA) < 0.f) { CollisionInfo* collision = collisions.getNewCollision(); if (collision) { collision->_penetration = surfaceBA; From 1782e803c9d7c82a50f04fdeb99aa950c860a1ec Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 18:21:39 -0700 Subject: [PATCH 16/76] remove include StreamUtils.h --- libraries/shared/src/ShapeCollider.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index c0de3cb90b..16624f9fec 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -15,7 +15,6 @@ #include "GeometryUtil.h" #include "ShapeCollider.h" -#include "StreamUtils.h" // NOTE: // From 63c02f2b04e846bb861b1176d39710a992999b7a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 18:22:34 -0700 Subject: [PATCH 17/76] add subscript operator for CollisionList --- libraries/shared/src/CollisionInfo.cpp | 3 +++ libraries/shared/src/CollisionInfo.h | 2 ++ 2 files changed, 5 insertions(+) diff --git a/libraries/shared/src/CollisionInfo.cpp b/libraries/shared/src/CollisionInfo.cpp index 5a4188a1ef..6b2f48f4d0 100644 --- a/libraries/shared/src/CollisionInfo.cpp +++ b/libraries/shared/src/CollisionInfo.cpp @@ -48,3 +48,6 @@ void CollisionList::clear() { _size = 0; } +const CollisionInfo* CollisionList::operator[](int index) const { + return (index > -1 && index < _size) ? &(_collisions[index]) : NULL; +} diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index f575dd8595..209a7e6127 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -95,6 +95,8 @@ public: /// Clear valid collisions. void clear(); + const CollisionInfo* operator[](int index) const; + private: int _maxSize; // the container cannot get larger than this int _size; // the current number of valid collisions in the list From 06794f33f3a4b480ec8158656af4e40c4ac7c472 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 21 Apr 2014 18:23:19 -0700 Subject: [PATCH 18/76] add accessor for Model::_boundingShape --- interface/src/renderer/Model.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 65b79fffdd..a14b58c11a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -193,6 +193,8 @@ public: /// Sets blended vertices computed in a separate thread. void setBlendedVertices(const QVector& vertices, const QVector& normals); + const CapsuleShape& getBoundingShape() const { return _boundingShape; } + protected: QSharedPointer _geometry; From 7cb6856415178e09a01c4e38e712f65c56143400 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 10:44:41 -0700 Subject: [PATCH 19/76] Adding some collision tests for sphere-vs-AACube --- tests/physics/src/ShapeColliderTests.cpp | 113 +++++++++++++++++++++++ tests/physics/src/ShapeColliderTests.h | 3 + 2 files changed, 116 insertions(+) diff --git a/tests/physics/src/ShapeColliderTests.cpp b/tests/physics/src/ShapeColliderTests.cpp index f9e76bac0b..fe1d79b456 100644 --- a/tests/physics/src/ShapeColliderTests.cpp +++ b/tests/physics/src/ShapeColliderTests.cpp @@ -699,6 +699,116 @@ void ShapeColliderTests::capsuleTouchesCapsule() { } } +void ShapeColliderTests::sphereTouchesAACube() { + CollisionList collisions(16); + + glm::vec3 cubeCenter(1.23f, 4.56f, 7.89f); + float cubeSide = 2.0f; + + float sphereRadius = 1.0f; + glm::vec3 sphereCenter(0.f); + SphereShape sphere(sphereRadius, sphereCenter); + + float sphereOffset = (0.5f * cubeSide + sphereRadius - 0.25f); + + // top + sphereCenter = cubeCenter + sphereOffset * yAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } + + // bottom + sphereCenter = cubeCenter - sphereOffset * yAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } + + // left + sphereCenter = cubeCenter + sphereOffset * xAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } + + // right + sphereCenter = cubeCenter - sphereOffset * xAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } + + // forward + sphereCenter = cubeCenter + sphereOffset * zAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } + + // back + sphereCenter = cubeCenter - sphereOffset * zAxis; + sphere.setPosition(sphereCenter); + if (!ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should collide with cube" << std::endl; + } +} + +void ShapeColliderTests::sphereMissesAACube() { + CollisionList collisions(16); + + glm::vec3 cubeCenter(1.23f, 4.56f, 7.89f); + float cubeSide = 2.0f; + + float sphereRadius = 1.0f; + glm::vec3 sphereCenter(0.0f); + SphereShape sphere(sphereRadius, sphereCenter); + + float sphereOffset = (0.5f * cubeSide + sphereRadius + 0.25f); + + // top + sphereCenter = cubeCenter + sphereOffset * yAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } + + // bottom + sphereCenter = cubeCenter - sphereOffset * yAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } + + // left + sphereCenter = cubeCenter + sphereOffset * xAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } + + // right + sphereCenter = cubeCenter - sphereOffset * xAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } + + // forward + sphereCenter = cubeCenter + sphereOffset * zAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } + + // back + sphereCenter = cubeCenter - sphereOffset * zAxis; + sphere.setPosition(sphereCenter); + if (ShapeCollider::sphereAACube(&sphere, cubeCenter, cubeSide, collisions)){ + std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should NOT collide with cube" << std::endl; + } +} + void ShapeColliderTests::runAllTests() { sphereMissesSphere(); @@ -709,4 +819,7 @@ void ShapeColliderTests::runAllTests() { capsuleMissesCapsule(); capsuleTouchesCapsule(); + + sphereTouchesAACube(); + sphereMissesAACube(); } diff --git a/tests/physics/src/ShapeColliderTests.h b/tests/physics/src/ShapeColliderTests.h index 1d468a65d2..a94f5050ff 100644 --- a/tests/physics/src/ShapeColliderTests.h +++ b/tests/physics/src/ShapeColliderTests.h @@ -23,6 +23,9 @@ namespace ShapeColliderTests { void capsuleMissesCapsule(); void capsuleTouchesCapsule(); + void sphereTouchesAACube(); + void sphereMissesAACube(); + void runAllTests(); } From a45bc6c110355a5d187b7906a55e6c550b7c36b7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 10:48:05 -0700 Subject: [PATCH 20/76] remove const from CollisionList subscript operator --- libraries/octree/src/Octree.cpp | 7 +++++-- libraries/shared/src/CollisionInfo.cpp | 2 +- libraries/shared/src/CollisionInfo.h | 2 +- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 83b84b3c50..4bd37d873a 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -707,7 +707,7 @@ bool findCapsulePenetrationOp(OctreeElement* node, void* extraData) { } bool findShapeCollisionsOp(OctreeElement* node, void* extraData) { - const ShapeArgs* args = static_cast(extraData); + ShapeArgs* args = static_cast(extraData); // coarse check against bounds AABox cube = node->getAABox(); @@ -719,7 +719,10 @@ bool findShapeCollisionsOp(OctreeElement* node, void* extraData) { return true; // recurse on children } if (node->hasContent()) { - return ShapeCollider::collideShapeWithAACube(args->shape, cube.calcCenter(), cube.getScale(), args->collisions); + if (ShapeCollider::collideShapeWithAACube(args->shape, cube.calcCenter(), cube.getScale(), args->collisions)) { + args->found = true; + return true; + } } return false; } diff --git a/libraries/shared/src/CollisionInfo.cpp b/libraries/shared/src/CollisionInfo.cpp index 6b2f48f4d0..5d97842530 100644 --- a/libraries/shared/src/CollisionInfo.cpp +++ b/libraries/shared/src/CollisionInfo.cpp @@ -48,6 +48,6 @@ void CollisionList::clear() { _size = 0; } -const CollisionInfo* CollisionList::operator[](int index) const { +CollisionInfo* CollisionList::operator[](int index) { return (index > -1 && index < _size) ? &(_collisions[index]) : NULL; } diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 209a7e6127..7db965fe64 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -95,7 +95,7 @@ public: /// Clear valid collisions. void clear(); - const CollisionInfo* operator[](int index) const; + CollisionInfo* operator[](int index); private: int _maxSize; // the container cannot get larger than this From 7537d240bb7a43db04d7020eb9ce02da5c1de142 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 10:48:42 -0700 Subject: [PATCH 21/76] toward working avatar-vs-voxel collisions again --- interface/src/avatar/MyAvatar.cpp | 28 ++++++++++++++++++++++++++ libraries/shared/src/ShapeCollider.cpp | 14 ++++++++----- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 8229611646..4ce1c2ad39 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -23,6 +23,7 @@ #include #include #include +#include #include @@ -795,7 +796,33 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) { } } +static CollisionList myCollisions(64); + void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { + static int foo = 0; + ++foo; + +// const float VOXEL_ELASTICITY = 0.4f; +// const float VOXEL_DAMPING = 0.0f; + const float VOXEL_COLLISION_FREQUENCY = 0.5f; + + myCollisions.clear(); + const CapsuleShape& boundingShape = _skeletonModel.getBoundingShape(); + if (Application::getInstance()->getVoxelTree()->findShapeCollisions(&boundingShape, myCollisions)) { + for (int i = 0; i < myCollisions.size(); ++i) { + CollisionInfo* collision = myCollisions[i]; + //if (0 == (foo % 100)) { + std::cout << "adebug " << myCollisions.size() << " collisions p = " << collision->_penetration << std::endl; // adebug + //} + //applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); + } + updateCollisionSound(myCollisions[0]->_penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); + } else if (myCollisions.size() == 0) { + if (0 == (foo % 100)) { + std::cout << "adebug 0 collisions capC = " << boundingShape.getPosition() << " capR = " << boundingShape.getRadius() << std::endl; // adebug + } + } + /* const float VOXEL_ELASTICITY = 0.4f; const float VOXEL_DAMPING = 0.0f; const float VOXEL_COLLISION_FREQUENCY = 0.5f; @@ -808,6 +835,7 @@ void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); } + */ } void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) { diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 16624f9fec..30bea1fef1 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -15,6 +15,7 @@ #include "GeometryUtil.h" #include "ShapeCollider.h" +#include "StreamUtils.h" // NOTE: // @@ -601,14 +602,17 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: // compute the nearest point on cube float maxBA = glm::max(glm::max(fabs(BA.x), fabs(BA.y)), fabs(BA.z)); glm::vec3 surfaceB = cubeCenter - (0.5f * cubeSide / maxBA) * BA; - // collision happens when "vector to surfaceB from surfaceA" dots with BA to produce a negative value - glm::vec3 surfaceBA = surfaceB - surfaceA; - if (glm::dot(surfaceBA, BA) < 0.f) { + // collision happens when "vector to surfaceA from surfaceB" dots with BA to produce a positive value + glm::vec3 surfaceAB = surfaceA - surfaceB; + if (glm::dot(surfaceAB, BA) > 0.f) { CollisionInfo* collision = collisions.getNewCollision(); if (collision) { - collision->_penetration = surfaceBA; + glm::vec3 normal(floorf(BA.x/maxBA), floorf(BA.y/maxBA), floorf(BA.z/maxBA)); + std::cout << "adebug normal = " << normal << std::endl; // adebug + normal = glm::normalize(normal); + collision->_penetration = glm::dot(surfaceAB, normal) * normal; // contactPoint is on surface of A - collision->_contactPoint = surfaceA; + collision->_contactPoint = sphereCenter - sphereRadius * normal; return true; } } From 65d3b4dc39ebe0887d52943f74f1ddf2e0c92370 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 11:43:23 -0700 Subject: [PATCH 22/76] fix penetration direction for sphere-vs-AACube --- libraries/shared/src/ShapeCollider.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 30bea1fef1..b4a1aaf90c 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -607,12 +607,15 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: if (glm::dot(surfaceAB, BA) > 0.f) { CollisionInfo* collision = collisions.getNewCollision(); if (collision) { - glm::vec3 normal(floorf(BA.x/maxBA), floorf(BA.y/maxBA), floorf(BA.z/maxBA)); - std::cout << "adebug normal = " << normal << std::endl; // adebug - normal = glm::normalize(normal); - collision->_penetration = glm::dot(surfaceAB, normal) * normal; + // penetration is parallel to box side direction + glm::vec3 direction; + modff(BA.x/maxBA, &(direction.x)); + modff(BA.y/maxBA, &(direction.y)); + modff(BA.z/maxBA, &(direction.z)); + direction = glm::normalize(direction); + collision->_penetration = glm::dot(surfaceAB, direction) * direction; // contactPoint is on surface of A - collision->_contactPoint = sphereCenter - sphereRadius * normal; + collision->_contactPoint = sphereCenter - sphereRadius * direction; return true; } } From 62121b1232e8d8c55f873fae2ec00129f540daed Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 11:46:15 -0700 Subject: [PATCH 23/76] remove include of StreamUtils.h again --- libraries/shared/src/ShapeCollider.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index b4a1aaf90c..458c355221 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -15,7 +15,6 @@ #include "GeometryUtil.h" #include "ShapeCollider.h" -#include "StreamUtils.h" // NOTE: // From 3eeb3a539dda788907121e1f32a5e9dc6883e242 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 22 Apr 2014 11:48:43 -0700 Subject: [PATCH 24/76] Fixed lack of resolution in usecTimestampNow() --- assignment-client/src/main.cpp | 1 + domain-server/src/main.cpp | 2 ++ interface/src/main.cpp | 1 + libraries/shared/src/SharedUtil.cpp | 22 +++++++++++++++++++--- libraries/shared/src/SharedUtil.h | 1 + 5 files changed, 24 insertions(+), 3 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 24d19ddef6..7132b5c38a 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -17,6 +17,7 @@ #include "AssignmentClientMonitor.h" int main(int argc, char* argv[]) { + initialiseUsecTimestampNow(); #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index bdb10cb56f..871c16a215 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -18,10 +18,12 @@ #include #include +#include #include "DomainServer.h" int main(int argc, char* argv[]) { + initialiseUsecTimestampNow(); #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 2bb0633f24..6f9dc5e3bd 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -16,6 +16,7 @@ #include int main(int argc, const char * argv[]) { + initialiseUsecTimestampNow(); QElapsedTimer startupTime; startupTime.start(); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index a13772d862..78ef997c35 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -21,18 +21,34 @@ #include #include +#include #include "OctalCode.h" #include "SharedUtil.h" -int usecTimestampNowAdjust = 0; + +static qint64 TIME_REFERENCE = 0; // in usec +static QElapsedTimer timestampTimer; +static int usecTimestampNowAdjust = 0; // in usec + +void initialiseUsecTimestampNow() { + static bool initialised = false; + if (initialised) { + qDebug() << "[WARNING] Double initialisation of usecTimestampNow()."; + return; + } + + TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec + initialised = true; +} + void usecTimestampNowForceClockSkew(int clockSkew) { ::usecTimestampNowAdjust = clockSkew; } quint64 usecTimestampNow() { - qint64 msecSinceEpoch = QDateTime::currentMSecsSinceEpoch(); - return msecSinceEpoch * 1000 + ::usecTimestampNowAdjust; + // usec nsec to usec usec + return TIME_REFERENCE + timestampTimer.nsecsElapsed() / 1000 + ::usecTimestampNowAdjust; } float randFloat() { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 4a3fe2a129..54d599070d 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -60,6 +60,7 @@ static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; const int BITS_IN_BYTE = 8; +void initialiseUsecTimestampNow(); quint64 usecTimestampNow(); void usecTimestampNowForceClockSkew(int clockSkew); From 0b9ebe4c081670c1d09a94e7033a62e2940a2fb9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 11:51:36 -0700 Subject: [PATCH 25/76] avatar-voxels collisions work again --- interface/src/avatar/MyAvatar.cpp | 35 +++++-------------------------- 1 file changed, 5 insertions(+), 30 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 99e6cba0c2..b7290641cb 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -799,43 +799,18 @@ void MyAvatar::updateCollisionWithEnvironment(float deltaTime, float radius) { static CollisionList myCollisions(64); void MyAvatar::updateCollisionWithVoxels(float deltaTime, float radius) { - static int foo = 0; - ++foo; - -// const float VOXEL_ELASTICITY = 0.4f; -// const float VOXEL_DAMPING = 0.0f; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; - myCollisions.clear(); const CapsuleShape& boundingShape = _skeletonModel.getBoundingShape(); if (Application::getInstance()->getVoxelTree()->findShapeCollisions(&boundingShape, myCollisions)) { + const float VOXEL_ELASTICITY = 0.4f; + const float VOXEL_DAMPING = 0.0f; for (int i = 0; i < myCollisions.size(); ++i) { CollisionInfo* collision = myCollisions[i]; - //if (0 == (foo % 100)) { - std::cout << "adebug " << myCollisions.size() << " collisions p = " << collision->_penetration << std::endl; // adebug - //} - //applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); + applyHardCollision(collision->_penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); } + const float VOXEL_COLLISION_FREQUENCY = 0.5f; updateCollisionSound(myCollisions[0]->_penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); - } else if (myCollisions.size() == 0) { - if (0 == (foo % 100)) { - std::cout << "adebug 0 collisions capC = " << boundingShape.getPosition() << " capR = " << boundingShape.getRadius() << std::endl; // adebug - } - } - /* - const float VOXEL_ELASTICITY = 0.4f; - const float VOXEL_DAMPING = 0.0f; - const float VOXEL_COLLISION_FREQUENCY = 0.5f; - glm::vec3 penetration; - float pelvisFloatingHeight = getPelvisFloatingHeight(); - if (Application::getInstance()->getVoxelTree()->findCapsulePenetration( - _position - glm::vec3(0.0f, pelvisFloatingHeight - radius, 0.0f), - _position + glm::vec3(0.0f, getSkeletonHeight() - pelvisFloatingHeight + radius, 0.0f), radius, penetration)) { - _lastCollisionPosition = _position; - updateCollisionSound(penetration, deltaTime, VOXEL_COLLISION_FREQUENCY); - applyHardCollision(penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); - } - */ + } } void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity, float damping) { From fea0a262a67f6316de8e32f418e413eaa0a54675 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Tue, 22 Apr 2014 12:35:50 -0700 Subject: [PATCH 26/76] Put back missing windows header --- libraries/shared/src/SharedUtil.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index 78ef997c35..b865d9c717 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -15,6 +15,10 @@ #include #include +#ifdef _WIN32 +#include +#endif + #ifdef __APPLE__ #include #endif From 364431328f25893420da51f25762830da3925309 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 14:26:40 -0700 Subject: [PATCH 27/76] remove include StreamUtils.h --- interface/src/avatar/MyAvatar.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index b7290641cb..c5639d5f00 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -23,7 +23,6 @@ #include #include #include -#include #include From f3fd81ca59fbe54d59dcd6c0ac3a3190cd4993e6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 14:26:52 -0700 Subject: [PATCH 28/76] use glm::modf() for less code --- libraries/shared/src/ShapeCollider.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 458c355221..3cd21cbcba 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -607,10 +607,9 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: CollisionInfo* collision = collisions.getNewCollision(); if (collision) { // penetration is parallel to box side direction + BA /= maxBA; glm::vec3 direction; - modff(BA.x/maxBA, &(direction.x)); - modff(BA.y/maxBA, &(direction.y)); - modff(BA.z/maxBA, &(direction.z)); + glm::modf(BA, direction); direction = glm::normalize(direction); collision->_penetration = glm::dot(surfaceAB, direction) * direction; // contactPoint is on surface of A From 1986ac6be334933c2b3bbba5e78c79fb4c2f8d3f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 20:53:12 -0700 Subject: [PATCH 29/76] collisions with cube get rounded normals at edges --- libraries/shared/src/ShapeCollider.cpp | 36 ++++++++++++++++++++++---- 1 file changed, 31 insertions(+), 5 deletions(-) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 3cd21cbcba..256c1aa388 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -606,11 +606,37 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: if (glm::dot(surfaceAB, BA) > 0.f) { CollisionInfo* collision = collisions.getNewCollision(); if (collision) { - // penetration is parallel to box side direction - BA /= maxBA; - glm::vec3 direction; - glm::modf(BA, direction); - direction = glm::normalize(direction); + // At this point imagine that sphereCenter touches a "normalized" cube with rounded edges. + // This cube has a sidelength of 2 and its smoothing radius is sphereRadius/maxBA. + // We're going to try to compute the "negative normal" (and hence direction of penetration) + // of this surface. + + float radius = sphereRadius / (distance * maxBA); // normalized radius + float shortLength = maxBA - radius; + glm::vec3 direction = BA; + if (shortLength > 0.0f) { + direction = glm::abs(BA) - glm::vec3(shortLength); + // Set any negative components to zero, and adopt the sign of the original BA component. + // Unfortunately there isn't an easy way to make this fast. + if (direction.x < 0.0f) { + direction.x = 0.f; + } else if (BA.x < 0.f) { + direction.x = -direction.x; + } + if (direction.y < 0.0f) { + direction.y = 0.f; + } else if (BA.y < 0.f) { + direction.y = -direction.y; + } + if (direction.z < 0.0f) { + direction.z = 0.f; + } else if (BA.z < 0.f) { + direction.z = -direction.z; + } + } + direction = glm::normalize(direction); + + // penetration is the projection of surfaceAB on direction collision->_penetration = glm::dot(surfaceAB, direction) * direction; // contactPoint is on surface of A collision->_contactPoint = sphereCenter - sphereRadius * direction; From 5992651c278e7e911525a3c9253dad13571163c1 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 22 Apr 2014 20:55:28 -0700 Subject: [PATCH 30/76] update avatar collision shapes when necessary --- interface/src/avatar/MyAvatar.cpp | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c5639d5f00..e1d7463aa3 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -335,15 +335,17 @@ void MyAvatar::simulate(float deltaTime) { radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f)); radius *= COLLISION_RADIUS_SCALAR; } - - if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { - updateCollisionWithEnvironment(deltaTime, radius); - } - if (_collisionFlags & COLLISION_GROUP_VOXELS) { - updateCollisionWithVoxels(deltaTime, radius); - } - if (_collisionFlags & COLLISION_GROUP_AVATARS) { - updateCollisionWithAvatars(deltaTime); + if (_collisionFlags) { + updateShapePositions(); + if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { + updateCollisionWithEnvironment(deltaTime, radius); + } + if (_collisionFlags & COLLISION_GROUP_VOXELS) { + updateCollisionWithVoxels(deltaTime, radius); + } + if (_collisionFlags & COLLISION_GROUP_AVATARS) { + updateCollisionWithAvatars(deltaTime); + } } } @@ -914,7 +916,6 @@ void MyAvatar::updateCollisionWithAvatars(float deltaTime) { // no need to compute a bunch of stuff if we have one or fewer avatars return; } - updateShapePositions(); float myBoundingRadius = getBoundingRadius(); const float BODY_COLLISION_RESOLUTION_FACTOR = glm::max(1.0f, deltaTime / BODY_COLLISION_RESOLUTION_TIMESCALE); From 7464ca0879bf8eb71a31e15ba61936ad6cf1b836 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 08:38:58 -0700 Subject: [PATCH 31/76] non-rounded collision solution in comments --- libraries/shared/src/ShapeCollider.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/libraries/shared/src/ShapeCollider.cpp b/libraries/shared/src/ShapeCollider.cpp index 256c1aa388..31d57f14ad 100644 --- a/libraries/shared/src/ShapeCollider.cpp +++ b/libraries/shared/src/ShapeCollider.cpp @@ -606,6 +606,16 @@ bool sphereAACube(const glm::vec3& sphereCenter, float sphereRadius, const glm:: if (glm::dot(surfaceAB, BA) > 0.f) { CollisionInfo* collision = collisions.getNewCollision(); if (collision) { + /* KEEP THIS CODE -- this is how to collide the cube with stark face normals (no rounding). + * We might want to use this code later for sealing boundaries between adjacent voxels. + // penetration is parallel to box side direction + BA /= maxBA; + glm::vec3 direction; + glm::modf(BA, direction); + direction = glm::normalize(direction); + */ + + // For rounded normals at edges and corners: // At this point imagine that sphereCenter touches a "normalized" cube with rounded edges. // This cube has a sidelength of 2 and its smoothing radius is sphereRadius/maxBA. // We're going to try to compute the "negative normal" (and hence direction of penetration) From da5ac3d6645665b5e1443c666396ec5b922da2ea Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 08:47:25 -0700 Subject: [PATCH 32/76] remove warning about signed/unsigned comparison --- domain-server/src/DomainServer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/domain-server/src/DomainServer.cpp b/domain-server/src/DomainServer.cpp index eb62dacf79..e65f3968e0 100644 --- a/domain-server/src/DomainServer.cpp +++ b/domain-server/src/DomainServer.cpp @@ -449,7 +449,7 @@ void DomainServer::sendDomainListToNode(const SharedNodePointer& node, const Hif if (nodeInterestList.size() > 0) { DTLSServerSession* dtlsSession = _isUsingDTLS ? _dtlsSessions[senderSockAddr] : NULL; - unsigned int dataMTU = dtlsSession ? gnutls_dtls_get_data_mtu(*dtlsSession->getGnuTLSSession()) : MAX_PACKET_SIZE; + int dataMTU = dtlsSession ? (int)gnutls_dtls_get_data_mtu(*dtlsSession->getGnuTLSSession()) : MAX_PACKET_SIZE; // if the node has any interest types, send back those nodes as well foreach (const SharedNodePointer& otherNode, nodeList->getNodeHash()) { From bfe1ee377ba16d3d3b9f377b4c912fa25caf0dd5 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 08:56:53 -0700 Subject: [PATCH 33/76] remove warning about signed/unsigned comparison Also change n.f to be n.0f as per coding standard --- interface/src/Audio.cpp | 53 +++++++++++++++++++---------------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index eb4a751356..0aba5a8ae5 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -480,7 +480,7 @@ void Audio::handleAudioInput() { float thisSample = 0; int samplesOverNoiseGate = 0; - const float NOISE_GATE_HEIGHT = 7.f; + const float NOISE_GATE_HEIGHT = 7.0f; const int NOISE_GATE_WIDTH = 5; const int NOISE_GATE_CLOSE_FRAME_DELAY = 5; const int NOISE_GATE_FRAMES_TO_AVERAGE = 5; @@ -490,7 +490,7 @@ void Audio::handleAudioInput() { // // Check clipping, adjust DC offset, and check if should open noise gate // - float measuredDcOffset = 0.f; + float measuredDcOffset = 0.0f; // Increment the time since the last clip if (_timeSinceLastClip >= 0.0f) { _timeSinceLastClip += (float) NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL / (float) SAMPLE_RATE; @@ -500,7 +500,7 @@ void Audio::handleAudioInput() { measuredDcOffset += monoAudioSamples[i]; monoAudioSamples[i] -= (int16_t) _dcOffset; thisSample = fabsf(monoAudioSamples[i]); - if (thisSample >= (32767.f * CLIPPING_THRESHOLD)) { + if (thisSample >= (32767.0f * CLIPPING_THRESHOLD)) { _timeSinceLastClip = 0.0f; } loudness += thisSample; @@ -511,18 +511,18 @@ void Audio::handleAudioInput() { } measuredDcOffset /= NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; - if (_dcOffset == 0.f) { + if (_dcOffset == 0.0f) { // On first frame, copy over measured offset _dcOffset = measuredDcOffset; } else { - _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.f - DC_OFFSET_AVERAGING) * measuredDcOffset; + _dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.0f - DC_OFFSET_AVERAGING) * measuredDcOffset; } // Add tone injection if enabled - const float TONE_FREQ = 220.f / SAMPLE_RATE * TWO_PI; - const float QUARTER_VOLUME = 8192.f; + const float TONE_FREQ = 220.0f / SAMPLE_RATE * TWO_PI; + const float QUARTER_VOLUME = 8192.0f; if (_toneInjectionEnabled) { - loudness = 0.f; + loudness = 0.0f; for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { monoAudioSamples[i] = QUARTER_VOLUME * sinf(TONE_FREQ * (float)(i + _proceduralEffectSample)); loudness += fabsf(monoAudioSamples[i]); @@ -532,7 +532,7 @@ void Audio::handleAudioInput() { // If Noise Gate is enabled, check and turn the gate on and off if (!_toneInjectionEnabled && _noiseGateEnabled) { - float averageOfAllSampleFrames = 0.f; + float averageOfAllSampleFrames = 0.0f; _noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness; if (_noiseGateSampleCounter == NUMBER_OF_NOISE_SAMPLE_FRAMES) { float smallestSample = FLT_MAX; @@ -660,9 +660,9 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { _stdev.reset(); // Set jitter buffer to be a multiple of the measured standard deviation const int MAX_JITTER_BUFFER_SAMPLES = _ringBuffer.getSampleCapacity() / 2; - const float NUM_STANDARD_DEVIATIONS = 3.f; + const float NUM_STANDARD_DEVIATIONS = 3.0f; if (Menu::getInstance()->getAudioJitterBufferSamples() == 0) { - float newJitterBufferSamples = (NUM_STANDARD_DEVIATIONS * _measuredJitter) / 1000.f * SAMPLE_RATE; + float newJitterBufferSamples = (NUM_STANDARD_DEVIATIONS * _measuredJitter) / 1000.0f * SAMPLE_RATE; setJitterBufferSamples(glm::clamp((int)newJitterBufferSamples, 0, MAX_JITTER_BUFFER_SAMPLES)); } } @@ -903,10 +903,10 @@ void Audio::toggleAudioSpatialProcessing() { void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { float sample; const float COLLISION_SOUND_CUTOFF_LEVEL = 0.01f; - const float COLLISION_SOUND_MAX_VOLUME = 1000.f; + const float COLLISION_SOUND_MAX_VOLUME = 1000.0f; const float UP_MAJOR_FIFTH = powf(1.5f, 4.0f); - const float DOWN_TWO_OCTAVES = 4.f; - const float DOWN_FOUR_OCTAVES = 16.f; + const float DOWN_TWO_OCTAVES = 4.0f; + const float DOWN_FOUR_OCTAVES = 16.0f; float t; if (_collisionSoundMagnitude > COLLISION_SOUND_CUTOFF_LEVEL) { for (int i = 0; i < numSamples; i++) { @@ -936,12 +936,12 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { _proceduralEffectSample += numSamples; // Add a drum sound - const float MAX_VOLUME = 32000.f; - const float MAX_DURATION = 2.f; + const float MAX_VOLUME = 32000.0f; + const float MAX_DURATION = 2.0f; const float MIN_AUDIBLE_VOLUME = 0.001f; const float NOISE_MAGNITUDE = 0.02f; float frequency = (_drumSoundFrequency / SAMPLE_RATE) * TWO_PI; - if (_drumSoundVolume > 0.f) { + if (_drumSoundVolume > 0.0f) { for (int i = 0; i < numSamples; i++) { t = (float) _drumSoundSample + (float) i; sample = sinf(t * frequency); @@ -961,12 +961,12 @@ void Audio::addProceduralSounds(int16_t* monoInput, int numSamples) { _localProceduralSamples[i] = glm::clamp(_localProceduralSamples[i] + collisionSample, MIN_SAMPLE_VALUE, MAX_SAMPLE_VALUE); - _drumSoundVolume *= (1.f - _drumSoundDecay); + _drumSoundVolume *= (1.0f - _drumSoundDecay); } _drumSoundSample += numSamples; - _drumSoundDuration = glm::clamp(_drumSoundDuration - (AUDIO_CALLBACK_MSECS / 1000.f), 0.f, MAX_DURATION); - if (_drumSoundDuration == 0.f || (_drumSoundVolume < MIN_AUDIBLE_VOLUME)) { - _drumSoundVolume = 0.f; + _drumSoundDuration = glm::clamp(_drumSoundDuration - (AUDIO_CALLBACK_MSECS / 1000.0f), 0.0f, MAX_DURATION); + if (_drumSoundDuration == 0.0f || (_drumSoundVolume < MIN_AUDIBLE_VOLUME)) { + _drumSoundVolume = 0.0f; } } } @@ -999,7 +999,7 @@ void Audio::renderToolBox(int x, int y, bool boxed) { if (boxed) { - bool isClipping = ((getTimeSinceLastClip() > 0.f) && (getTimeSinceLastClip() < 1.f)); + bool isClipping = ((getTimeSinceLastClip() > 0.0f) && (getTimeSinceLastClip() < 1.0f)); const int BOX_LEFT_PADDING = 5; const int BOX_TOP_PADDING = 10; const int BOX_WIDTH = 266; @@ -1010,9 +1010,9 @@ void Audio::renderToolBox(int x, int y, bool boxed) { glBindTexture(GL_TEXTURE_2D, _boxTextureId); if (isClipping) { - glColor3f(1.f,0.f,0.f); + glColor3f(1.0f, 0.0f, 0.0f); } else { - glColor3f(.41f,.41f,.41f); + glColor3f(0.41f, 0.41f, 0.41f); } glBegin(GL_QUADS); @@ -1089,10 +1089,8 @@ void Audio::addBufferToScope( // Short int pointer to mapped samples in byte array int16_t* destination = (int16_t*) byteArray.data(); - for (int i = 0; i < NETWORK_SAMPLES_PER_FRAME; i++) { - + for (unsigned int i = 0; i < NETWORK_SAMPLES_PER_FRAME; i++) { sample = (float)source[i * sourceNumberOfChannels + sourceChannel]; - if (sample > 0) { value = (int16_t)(multiplier * logf(sample)); } else if (sample < 0) { @@ -1100,7 +1098,6 @@ void Audio::addBufferToScope( } else { value = 0; } - destination[i + frameOffset] = value; } } From a7771bc142e48d2ebf022445f78878346315fce0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 09:05:11 -0700 Subject: [PATCH 34/76] repair header comments for AABox.* --- libraries/octree/src/AABox.cpp | 2 +- libraries/octree/src/AABox.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/octree/src/AABox.cpp b/libraries/octree/src/AABox.cpp index ed99a24d38..51b31d4466 100644 --- a/libraries/octree/src/AABox.cpp +++ b/libraries/octree/src/AABox.cpp @@ -1,6 +1,6 @@ // // AABox.cpp -// libraries/shared/src +// libraries/octree/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. diff --git a/libraries/octree/src/AABox.h b/libraries/octree/src/AABox.h index 6531db4250..1aa0849b70 100644 --- a/libraries/octree/src/AABox.h +++ b/libraries/octree/src/AABox.h @@ -1,6 +1,6 @@ // // AABox.h -// libraries/shared/src +// libraries/octree/src // // Created by Brad Hefta-Gaub on 04/11/13. // Copyright 2013 High Fidelity, Inc. From f46a5dc96670f77ece6acf7c189db2ba4cb53624 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 10:13:05 -0700 Subject: [PATCH 35/76] fix #2718 for warning about unused variable --- interface/src/ui/ScriptEditorWidget.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/ui/ScriptEditorWidget.cpp b/interface/src/ui/ScriptEditorWidget.cpp index 1765a5ea1a..3f9b0137ef 100644 --- a/interface/src/ui/ScriptEditorWidget.cpp +++ b/interface/src/ui/ScriptEditorWidget.cpp @@ -39,7 +39,8 @@ ScriptEditorWidget::ScriptEditorWidget() : setTitleBarWidget(new QWidget()); QFontMetrics fm(_scriptEditorWidgetUI->scriptEdit->font()); _scriptEditorWidgetUI->scriptEdit->setTabStopWidth(fm.width('0') * 4); - ScriptHighlighting* highlighting = new ScriptHighlighting(_scriptEditorWidgetUI->scriptEdit->document()); + // We create a new ScriptHighligting QObject and provide it with a parent so this is NOT a memory leak. + new ScriptHighlighting(_scriptEditorWidgetUI->scriptEdit->document()); QTimer::singleShot(0, _scriptEditorWidgetUI->scriptEdit, SLOT(setFocus())); } From 378afdf117fb2617232b636311b34dcd27a3e2d9 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 23 Apr 2014 10:35:24 -0700 Subject: [PATCH 36/76] More undo work --- libraries/voxels/src/VoxelTree.cpp | 2 +- libraries/voxels/src/VoxelTreeCommands.cpp | 26 ++++------------------ 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index bb9de72e9d..3a77382a84 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -42,7 +42,7 @@ void VoxelTree::deleteVoxelAt(float x, float y, float z, float s) { } VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) const { - return (VoxelTreeElement*)getOctreeElementAt(x, y, z, s); + return static_cast(getOctreeElementAt(x, y, z, s)); } void VoxelTree::createVoxel(float x, float y, float z, float s, diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index 75b38667ec..46837aa23e 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -22,27 +22,8 @@ AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditP { VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); if (element) { - if (element->hasContent() && element->isLeaf()) { - // Do nothing, everything is in order - } else { - _oldTree = new VoxelTree(); - _tree->copySubTreeIntoNewTree(element, _oldTree, true); - } - } else { - glm::vec3 point(_voxel.x + _voxel.s / 2.0f, - _voxel.y + _voxel.s / 2.0f, - _voxel.z + _voxel.s / 2.0f); - OctreeElement* element = _tree->getElementEnclosingPoint(point, Octree::Lock); - if (element) { - VoxelTreeElement* node = static_cast(element); - _voxel.x = node->getCorner().x; - _voxel.y = node->getCorner().y; - _voxel.z = node->getCorner().z; - _voxel.s = node->getScale(); - _voxel.red = node->getColor()[0]; - _voxel.green = node->getColor()[1]; - _voxel.blue = node->getColor()[2]; - } + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, true); } } @@ -62,8 +43,9 @@ void AddVoxelCommand::redo() { void AddVoxelCommand::undo() { if (_oldTree) { OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - qDebug() << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; + qDebug() << "undo(): " << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; _tree->copyFromTreeIntoSubTree(_oldTree, element); + qDebug() << "done"; } else { if (_tree) { _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); From f7bc1ae62c310de94375629d63bce7cbad257561 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 10:47:24 -0700 Subject: [PATCH 37/76] Working on integrating rotation into IK. --- interface/src/avatar/SkeletonModel.cpp | 25 +++++------------- interface/src/renderer/Model.cpp | 36 +++++++++++++++++--------- interface/src/renderer/Model.h | 5 ++-- 3 files changed, 34 insertions(+), 32 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 1c6a568754..6581bc1841 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -148,17 +148,12 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } const FBXGeometry& geometry = _geometry->getFBXGeometry(); float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; - int parentJointIndex = geometry.joints.at(jointIndex).parentIndex; - if (parentJointIndex == -1) { - return; - } - // rotate forearm to align with palm direction + // rotate palm to align with palm direction glm::quat palmRotation; - getJointRotation(parentJointIndex, palmRotation, true); - applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()), true, true); - getJointRotation(parentJointIndex, palmRotation, true); - + getJointRotation(jointIndex, palmRotation, true); + palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; + // sort the finger indices by raw x, get the average direction QVector fingerIndices; glm::vec3 direction; @@ -178,18 +173,12 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin float directionLength = glm::length(direction); const unsigned int MIN_ROTATION_FINGERS = 3; if (directionLength > EPSILON && palm.getNumFingers() >= MIN_ROTATION_FINGERS) { - applyRotationDelta(parentJointIndex, rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction), - true, true); - getJointRotation(parentJointIndex, palmRotation, true); + palmRotation = rotationBetween(palmRotation * glm::vec3(-sign, 0.0f, 0.0f), direction) * palmRotation; } - // let wrist inherit forearm rotation - _jointStates[jointIndex].rotation = glm::quat(); - - // set elbow position from wrist position + // set hand position, rotation glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); - setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * - geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale)); + setJointPosition(jointIndex, palm.getPosition(), palmRotation); } void SkeletonModel::updateJointState(int index) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index b373ffa545..9aa5bd8227 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -882,12 +882,12 @@ bool Model::getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind) return true; } -bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int lastFreeIndex, - bool allIntermediatesFree, const glm::vec3& alignment) { +bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation, bool useRotation, + int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment) { if (jointIndex == -1 || _jointStates.isEmpty()) { return false; } - glm::vec3 relativePosition = position - _translation; + glm::vec3 relativePosition = translation - _translation; const FBXGeometry& geometry = _geometry->getFBXGeometry(); const QVector& freeLineage = geometry.joints.at(jointIndex).freeLineage; if (freeLineage.isEmpty()) { @@ -897,17 +897,20 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int last lastFreeIndex = freeLineage.last(); } - // now update the joint states from the top - for (int j = freeLineage.size() - 1; j >= 0; j--) { - updateJointState(freeLineage.at(j)); - } - // this is a cyclic coordinate descent algorithm: see // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d const int ITERATION_COUNT = 1; glm::vec3 worldAlignment = _rotation * alignment; for (int i = 0; i < ITERATION_COUNT; i++) { - // first, we go from the joint upwards, rotating the end as close as possible to the target + // first, try to rotate the end effector as close as possible to the target rotation, if any + glm::quat endRotation; + if (useRotation) { + getJointRotation(jointIndex, endRotation, true); + applyRotationDelta(jointIndex, rotation * glm::inverse(endRotation)); + getJointRotation(jointIndex, endRotation, true); + } + + // then, we go from the joint upwards, rotating the end as close as possible to the target glm::vec3 endPosition = extractTranslation(_jointStates[jointIndex].transform); for (int j = 1; freeLineage.at(j - 1) != lastFreeIndex; j++) { int index = freeLineage.at(j); @@ -919,8 +922,17 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, int last glm::vec3 jointPosition = extractTranslation(state.transform); glm::vec3 jointVector = endPosition - jointPosition; glm::quat oldCombinedRotation = state.combinedRotation; - applyRotationDelta(index, rotationBetween(jointVector, relativePosition - jointPosition)); - endPosition = state.combinedRotation * glm::inverse(oldCombinedRotation) * jointVector + jointPosition; + if (useRotation) { + applyRotationDelta(index, safeMix(rotationBetween(jointVector, relativePosition - jointPosition), + rotation * glm::inverse(endRotation), 0.5f)); + glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation); + endRotation = actualDelta * endRotation; + endPosition = actualDelta * jointVector + jointPosition; + + } else { + applyRotationDelta(index, rotationBetween(jointVector, relativePosition - jointPosition)); + endPosition = state.combinedRotation * glm::inverse(oldCombinedRotation) * jointVector + jointPosition; + } if (alignment != glm::vec3() && j > 1) { jointVector = endPosition - jointPosition; glm::vec3 positionSum; @@ -1154,7 +1166,7 @@ void Model::applyCollision(CollisionInfo& collision) { getJointPosition(jointIndex, end); glm::vec3 newEnd = start + glm::angleAxis(angle, axis) * (end - start); // try to move it - setJointPosition(jointIndex, newEnd, -1, true); + setJointPosition(jointIndex, newEnd, glm::quat(), false, -1, true); } } } diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index b472e17b20..10e9e2a66a 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -240,8 +240,9 @@ protected: bool getJointPosition(int jointIndex, glm::vec3& position) const; bool getJointRotation(int jointIndex, glm::quat& rotation, bool fromBind = false) const; - bool setJointPosition(int jointIndex, const glm::vec3& position, int lastFreeIndex = -1, - bool allIntermediatesFree = false, const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f)); + bool setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat& rotation = glm::quat(), + bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false, + const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f)); bool setJointRotation(int jointIndex, const glm::quat& rotation, bool fromBind = false); void setJointTranslation(int jointIndex, const glm::vec3& translation); From ceb5208102f6d5ea8c2a5a5909c966b2c8ac5a77 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 23 Apr 2014 11:00:44 -0700 Subject: [PATCH 38/76] CR --- interface/src/Application.cpp | 5 ++--- interface/src/Util.cpp | 25 +++++++++++++------------ interface/src/starfield/Controller.cpp | 3 ++- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index bfbc88a666..265ff2e7a1 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1218,8 +1218,7 @@ void Application::touchEndEvent(QTouchEvent* event) { if (_controllerScriptingInterface.isTouchCaptured()) { return; } - - // put any application specific touch behavior below here.. +s // put any application specific touch behavior below here.. _touchDragStartedAvgX = _touchAvgX; _touchDragStartedAvgY = _touchAvgY; _isTouchPressed = false; @@ -1276,7 +1275,7 @@ void Application::timer() { sendPingPackets(); } - float diffTime = (float)_timerStart.nsecsElapsed() / 1000000000.0; + float diffTime = (float)_timerStart.nsecsElapsed() / 1000000000.0f; _fps = (float)_frameCount / diffTime; diff --git a/interface/src/Util.cpp b/interface/src/Util.cpp index 16dd35f316..79a2e31d80 100644 --- a/interface/src/Util.cpp +++ b/interface/src/Util.cpp @@ -407,24 +407,25 @@ void runTimingTests() { startTime.start(); float elapsedUsecs; - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("QElapsedTimer::nsecElapsed() usecs: %f", 1000.0f * elapsedUsecs / (float) numTests); + float NSEC_TO_USEC = 1.0f / 1000.0f; + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + qDebug("QElapsedTimer::nsecElapsed() usecs: %f", elapsedUsecs / (float) numTests); // Random number generation startTime.start(); for (int i = 1; i < numTests; i++) { iResults[i] = rand(); } - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("rand() stored in array usecs: %f, first result:%d", 1000.0f * elapsedUsecs / (float) numTests, iResults[0]); + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + qDebug("rand() stored in array usecs: %f, first result:%d", elapsedUsecs / (float) numTests, iResults[0]); // Random number generation using randFloat() startTime.start(); for (int i = 1; i < numTests; i++) { fResults[i] = randFloat(); } - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("randFloat() stored in array usecs: %f, first result: %f", 1000.0f * elapsedUsecs / (float) numTests, fResults[0]); + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + qDebug("randFloat() stored in array usecs: %f, first result: %f", elapsedUsecs / (float) numTests, fResults[0]); // PowF function fTest = 1145323.2342f; @@ -432,8 +433,8 @@ void runTimingTests() { for (int i = 1; i < numTests; i++) { fTest = powf(fTest, 0.5f); } - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("powf(f, 0.5) usecs: %f", 1000.0f * elapsedUsecs / (float) numTests); + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + qDebug("powf(f, 0.5) usecs: %f", elapsedUsecs / (float) numTests); // Vector Math float distance; @@ -444,9 +445,9 @@ void runTimingTests() { //float distanceSquared = glm::dot(temp, temp); distance = glm::distance(pointA, pointB); } - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; qDebug("vector math usecs: %f [%f usecs total for %d tests], last result:%f", - 1000.0f * elapsedUsecs / (float) numTests, elapsedUsecs, numTests, distance); + elapsedUsecs / (float) numTests, elapsedUsecs, numTests, distance); // Vec3 test glm::vec3 vecA(randVector()), vecB(randVector()); @@ -457,8 +458,8 @@ void runTimingTests() { glm::vec3 temp = vecA-vecB; result = glm::dot(temp,temp); } - elapsedUsecs = (float)startTime.nsecsElapsed() / 1000.0; - qDebug("vec3 assign and dot() usecs: %f, last result:%f", 1000.0f * elapsedUsecs / (float) numTests, result); + elapsedUsecs = (float)startTime.nsecsElapsed() * NSEC_TO_USEC; + qDebug("vec3 assign and dot() usecs: %f, last result:%f", elapsedUsecs / (float) numTests, result); } float loadSetting(QSettings* settings, const char* name, float defaultValue) { diff --git a/interface/src/starfield/Controller.cpp b/interface/src/starfield/Controller.cpp index e68243752c..2279a68422 100755 --- a/interface/src/starfield/Controller.cpp +++ b/interface/src/starfield/Controller.cpp @@ -23,7 +23,8 @@ bool Controller::computeStars(unsigned numStars, unsigned seed) { this->retile(numStars, _tileResolution); - double timeDiff = (double)startTime.nsecsElapsed() / 1000000.0; // ns to ms + double NSEC_TO_MSEC = 1.0 / 1000000.0; + double timeDiff = (double)startTime.nsecsElapsed() * NSEC_TO_MSEC; qDebug() << "Total time to retile and generate stars: " << timeDiff << "msec"; return true; From f68d2d16a83449fb6a61c6cb19bf3453ffb8bdc3 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 23 Apr 2014 11:05:16 -0700 Subject: [PATCH 39/76] Inserted a char by mistake --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 265ff2e7a1..4adb2f772a 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1218,7 +1218,7 @@ void Application::touchEndEvent(QTouchEvent* event) { if (_controllerScriptingInterface.isTouchCaptured()) { return; } -s // put any application specific touch behavior below here.. + // put any application specific touch behavior below here.. _touchDragStartedAvgX = _touchAvgX; _touchDragStartedAvgY = _touchAvgY; _isTouchPressed = false; From 511fc8367f425eb0c6c9f4f55221cf0747555d7b Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 11:34:34 -0700 Subject: [PATCH 40/76] More work on IK. --- interface/src/avatar/SkeletonModel.cpp | 3 +-- interface/src/renderer/Model.cpp | 26 +++++++++++++++----------- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 6581bc1841..f52858b4ff 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -177,8 +177,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } // set hand position, rotation - glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); - setJointPosition(jointIndex, palm.getPosition(), palmRotation); + setJointPosition(jointIndex, palm.getPosition(), palmRotation, true); } void SkeletonModel::updateJointState(int index) { diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9aa5bd8227..77d9743cd5 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -896,6 +896,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const if (lastFreeIndex == -1) { lastFreeIndex = freeLineage.last(); } + float baseWeight = 1.0f / (freeLineage.indexOf(lastFreeIndex) + (useRotation ? 1 : 0)); // this is a cyclic coordinate descent algorithm: see // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d @@ -906,7 +907,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat endRotation; if (useRotation) { getJointRotation(jointIndex, endRotation, true); - applyRotationDelta(jointIndex, rotation * glm::inverse(endRotation)); + applyRotationDelta(jointIndex, safeMix(glm::quat(), rotation * glm::inverse(endRotation), baseWeight)); getJointRotation(jointIndex, endRotation, true); } @@ -922,17 +923,13 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::vec3 jointPosition = extractTranslation(state.transform); glm::vec3 jointVector = endPosition - jointPosition; glm::quat oldCombinedRotation = state.combinedRotation; + glm::quat combinedDelta; + float combinedWeight = 0.0f; if (useRotation) { - applyRotationDelta(index, safeMix(rotationBetween(jointVector, relativePosition - jointPosition), - rotation * glm::inverse(endRotation), 0.5f)); - glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation); - endRotation = actualDelta * endRotation; - endPosition = actualDelta * jointVector + jointPosition; - - } else { - applyRotationDelta(index, rotationBetween(jointVector, relativePosition - jointPosition)); - endPosition = state.combinedRotation * glm::inverse(oldCombinedRotation) * jointVector + jointPosition; + combinedDelta = safeMix(combinedDelta, rotation * glm::inverse(endRotation), baseWeight / (combinedWeight += 1.0f)); } + combinedDelta = safeMix(combinedDelta, rotationBetween(jointVector, relativePosition - jointPosition), + baseWeight / (combinedWeight += 1.0f)); if (alignment != glm::vec3() && j > 1) { jointVector = endPosition - jointPosition; glm::vec3 positionSum; @@ -946,9 +943,16 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::vec3 projectedAlignment = glm::cross(jointVector, glm::cross(worldAlignment, jointVector)); const float LENGTH_EPSILON = 0.001f; if (glm::length(projectedCenterOfMass) > LENGTH_EPSILON && glm::length(projectedAlignment) > LENGTH_EPSILON) { - applyRotationDelta(index, rotationBetween(projectedCenterOfMass, projectedAlignment)); + combinedDelta = safeMix(combinedDelta, rotationBetween(projectedCenterOfMass, projectedAlignment), + baseWeight / (combinedWeight += 1.0f)); } } + applyRotationDelta(index, combinedDelta); + glm::quat actualDelta = state.combinedRotation * glm::inverse(oldCombinedRotation); + endPosition = actualDelta * jointVector + jointPosition; + if (useRotation) { + endRotation = actualDelta * endRotation; + } } } From 359c14e3191333e8d4300b56c64cf529d3b2175f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 11:48:42 -0700 Subject: [PATCH 41/76] cleanup: remove unused Avatar::_mode The mode, if it is required, should probably eventually live in AvatarDAta since it will be determined by whatever engine is running the avatar (script or interface) and then broadcast to the rest of the world. When we need it we'll add it back in the right place. --- interface/src/avatar/Avatar.cpp | 13 ++----------- interface/src/avatar/Avatar.h | 8 -------- interface/src/avatar/MyAvatar.cpp | 10 +--------- interface/src/avatar/MyAvatar.h | 1 - 4 files changed, 3 insertions(+), 29 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index fe685b89f8..5173caa051 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -47,7 +47,6 @@ Avatar::Avatar() : AvatarData(), _skeletonModel(this), _bodyYawDelta(0.0f), - _mode(AVATAR_MODE_STANDING), _velocity(0.0f, 0.0f, 0.0f), _thrust(0.0f, 0.0f, 0.0f), _leanScale(0.5f), @@ -138,19 +137,11 @@ void Avatar::simulate(float deltaTime) { head->simulate(deltaTime, false, _shouldRenderBillboard); } - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > 0.2) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update position by velocity, and subtract the change added earlier for gravity _position += _velocity * deltaTime; // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0, 0, 0); + _thrust = glm::vec3(0.0f); // update animation for display name fade in/out if ( _displayNameTargetAlpha != _displayNameAlpha) { @@ -166,7 +157,7 @@ void Avatar::simulate(float deltaTime) { // Fading in _displayNameAlpha = 1 - (1 - _displayNameAlpha) * coef; } - _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01? _displayNameTargetAlpha : _displayNameAlpha; + _displayNameAlpha = abs(_displayNameAlpha - _displayNameTargetAlpha) < 0.01f ? _displayNameTargetAlpha : _displayNameAlpha; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index ecf1be4899..39cc174e69 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -46,13 +46,6 @@ enum DriveKeys { MAX_DRIVE_KEYS }; -enum AvatarMode { - AVATAR_MODE_STANDING = 0, - AVATAR_MODE_WALKING, - AVATAR_MODE_INTERACTING, - NUM_AVATAR_MODES -}; - enum ScreenTintLayer { SCREEN_TINT_BEFORE_LANDSCAPE = 0, SCREEN_TINT_BEFORE_AVATARS, @@ -164,7 +157,6 @@ signals: protected: SkeletonModel _skeletonModel; float _bodyYawDelta; - AvatarMode _mode; glm::vec3 _velocity; glm::vec3 _thrust; float _leanScale; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index e1d7463aa3..de0c507272 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -269,17 +269,9 @@ void MyAvatar::simulate(float deltaTime) { // update the euler angles setOrientation(orientation); - const float WALKING_SPEED_THRESHOLD = 0.2f; - // use speed and angular velocity to determine walking vs. standing - float speed = glm::length(_velocity); - if (speed + fabs(_bodyYawDelta) > WALKING_SPEED_THRESHOLD) { - _mode = AVATAR_MODE_WALKING; - } else { - _mode = AVATAR_MODE_INTERACTING; - } - // update moving flag based on speed const float MOVING_SPEED_THRESHOLD = 0.01f; + float speed = glm::length(_velocity); _moving = speed > MOVING_SPEED_THRESHOLD; // If a move target is set, update position explicitly diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 71c74f7c91..f6c83c7ac4 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -54,7 +54,6 @@ public: void setShouldRenderLocally(bool shouldRender) { _shouldRender = shouldRender; } // getters - AvatarMode getMode() const { return _mode; } float getLeanScale() const { return _leanScale; } float getElapsedTimeStopped() const { return _elapsedTimeStopped; } float getElapsedTimeMoving() const { return _elapsedTimeMoving; } From 523498ee5b918b4cbc5a0930522fddd09dc51274 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 11:52:22 -0700 Subject: [PATCH 42/76] Revert to using weight that doesn't depend on number of free joints. --- interface/src/renderer/Model.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 77d9743cd5..143b6a8109 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -896,8 +896,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const if (lastFreeIndex == -1) { lastFreeIndex = freeLineage.last(); } - float baseWeight = 1.0f / (freeLineage.indexOf(lastFreeIndex) + (useRotation ? 1 : 0)); - + // this is a cyclic coordinate descent algorithm: see // http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d const int ITERATION_COUNT = 1; @@ -907,7 +906,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat endRotation; if (useRotation) { getJointRotation(jointIndex, endRotation, true); - applyRotationDelta(jointIndex, safeMix(glm::quat(), rotation * glm::inverse(endRotation), baseWeight)); + applyRotationDelta(jointIndex, rotation * glm::inverse(endRotation)); getJointRotation(jointIndex, endRotation, true); } @@ -924,12 +923,15 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::vec3 jointVector = endPosition - jointPosition; glm::quat oldCombinedRotation = state.combinedRotation; glm::quat combinedDelta; - float combinedWeight = 0.0f; + float combinedWeight; if (useRotation) { - combinedDelta = safeMix(combinedDelta, rotation * glm::inverse(endRotation), baseWeight / (combinedWeight += 1.0f)); + combinedDelta = rotation * glm::inverse(endRotation); + combinedWeight = 1.0f; + } else { + combinedDelta = safeMix(rotation * glm::inverse(endRotation), + rotationBetween(jointVector, relativePosition - jointPosition), 0.5f); + combinedWeight = 2.0f; } - combinedDelta = safeMix(combinedDelta, rotationBetween(jointVector, relativePosition - jointPosition), - baseWeight / (combinedWeight += 1.0f)); if (alignment != glm::vec3() && j > 1) { jointVector = endPosition - jointPosition; glm::vec3 positionSum; @@ -944,7 +946,7 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const const float LENGTH_EPSILON = 0.001f; if (glm::length(projectedCenterOfMass) > LENGTH_EPSILON && glm::length(projectedAlignment) > LENGTH_EPSILON) { combinedDelta = safeMix(combinedDelta, rotationBetween(projectedCenterOfMass, projectedAlignment), - baseWeight / (combinedWeight += 1.0f)); + 1.0f / (combinedWeight + 1.0f)); } } applyRotationDelta(index, combinedDelta); From 09bb51261a14b471804611403c9228a56880de7d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 11:55:16 -0700 Subject: [PATCH 43/76] Got that backwards. --- interface/src/renderer/Model.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 143b6a8109..26e59635bb 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -925,12 +925,13 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& translation, const glm::quat combinedDelta; float combinedWeight; if (useRotation) { - combinedDelta = rotation * glm::inverse(endRotation); - combinedWeight = 1.0f; - } else { combinedDelta = safeMix(rotation * glm::inverse(endRotation), rotationBetween(jointVector, relativePosition - jointPosition), 0.5f); combinedWeight = 2.0f; + + } else { + combinedDelta = rotationBetween(jointVector, relativePosition - jointPosition); + combinedWeight = 1.0f; } if (alignment != glm::vec3() && j > 1) { jointVector = endPosition - jointPosition; From 37a5d9130f6ae6050cdfc47adb15083f0f2c7664 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 11:55:28 -0700 Subject: [PATCH 44/76] move _thrust from Avatar to MyAvatar --- interface/src/avatar/Avatar.cpp | 4 ---- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 3 ++- interface/src/avatar/MyAvatar.h | 1 + 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 5173caa051..2df1fd2302 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -48,7 +48,6 @@ Avatar::Avatar() : _skeletonModel(this), _bodyYawDelta(0.0f), _velocity(0.0f, 0.0f, 0.0f), - _thrust(0.0f, 0.0f, 0.0f), _leanScale(0.5f), _scale(1.0f), _worldUpDirection(DEFAULT_UP_DIRECTION), @@ -140,9 +139,6 @@ void Avatar::simulate(float deltaTime) { // update position by velocity, and subtract the change added earlier for gravity _position += _velocity * deltaTime; - // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0.0f); - // update animation for display name fade in/out if ( _displayNameTargetAlpha != _displayNameAlpha) { // the alpha function is diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 39cc174e69..805a60d425 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -158,7 +158,6 @@ protected: SkeletonModel _skeletonModel; float _bodyYawDelta; glm::vec3 _velocity; - glm::vec3 _thrust; float _leanScale; float _scale; glm::vec3 _worldUpDirection; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index de0c507272..33a1127a64 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -59,6 +59,7 @@ MyAvatar::MyAvatar() : _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), + _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), _moveTarget(0,0,0), @@ -316,7 +317,7 @@ void MyAvatar::simulate(float deltaTime) { head->simulate(deltaTime, true); // Zero thrust out now that we've added it to velocity in this frame - _thrust = glm::vec3(0.0f); + _thrust *= glm::vec3(0.0f); // now that we're done stepping the avatar forward in time, compute new collisions if (_collisionFlags != 0) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index f6c83c7ac4..5cdb13682f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -122,6 +122,7 @@ private: float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; + glm::vec3 _thrust; bool _isThrustOn; float _thrustMultiplier; glm::vec3 _moveTarget; From 0386dec2a67e0f8d450d7f49c8643bb82c9427ba Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 12:09:54 -0700 Subject: [PATCH 45/76] Provide option to align wrists with forearms. --- interface/src/Menu.cpp | 1 + interface/src/Menu.h | 1 + interface/src/avatar/SkeletonModel.cpp | 20 ++++++++++++++++++-- 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 0a0bd599eb..a7012d838d 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -336,6 +336,7 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::PlaySlaps, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::HandsCollideWithSelf, 0, false); addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::ShowIKConstraints, 0, false); + addCheckableActionToQMenuAndActionHash(handOptionsMenu, MenuOption::AlignForearmsWithWrists, 0, true); addDisabledActionAndSeparator(developerMenu, "Testing"); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index f9f97be379..09b5fabfc8 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -256,6 +256,7 @@ private: namespace MenuOption { const QString AboutApp = "About Interface"; + const QString AlignForearmsWithWrists = "Align Forearms with Wrists"; const QString AmbientOcclusion = "Ambient Occlusion"; const QString Atmosphere = "Atmosphere"; const QString AudioNoiseReduction = "Audio Noise Reduction"; diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index f52858b4ff..4bb7814300 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -148,10 +148,18 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } const FBXGeometry& geometry = _geometry->getFBXGeometry(); float sign = (jointIndex == geometry.rightHandJointIndex) ? 1.0f : -1.0f; + int parentJointIndex = geometry.joints.at(jointIndex).parentIndex; + if (parentJointIndex == -1) { + return; + } // rotate palm to align with palm direction glm::quat palmRotation; - getJointRotation(jointIndex, palmRotation, true); + if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { + getJointRotation(parentJointIndex, palmRotation, true); + } else { + getJointRotation(jointIndex, palmRotation, true); + } palmRotation = rotationBetween(palmRotation * geometry.palmDirection, palm.getNormal()) * palmRotation; // sort the finger indices by raw x, get the average direction @@ -177,7 +185,15 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin } // set hand position, rotation - setJointPosition(jointIndex, palm.getPosition(), palmRotation, true); + if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { + glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); + setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * + geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), palmRotation, true); + _jointStates[jointIndex].rotation = glm::quat(); + + } else { + setJointPosition(jointIndex, palm.getPosition(), palmRotation, true); + } } void SkeletonModel::updateJointState(int index) { From 39c193a679c56dd565d9307ac51c9a3bcfe9f962 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 12:15:15 -0700 Subject: [PATCH 46/76] remove unused getElapsedTime*() methods --- interface/src/avatar/MyAvatar.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 5cdb13682f..592e1172af 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -55,8 +55,6 @@ public: // getters float getLeanScale() const { return _leanScale; } - float getElapsedTimeStopped() const { return _elapsedTimeStopped; } - float getElapsedTimeMoving() const { return _elapsedTimeMoving; } const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; } const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; } glm::vec3 getGravity() const { return _gravity; } @@ -117,14 +115,17 @@ private: float _driveKeys[MAX_DRIVE_KEYS]; glm::vec3 _gravity; float _distanceToNearestAvatar; // How close is the nearest avatar? + + // motion stuff float _elapsedTimeMoving; // Timers to drive camera transitions when moving float _elapsedTimeStopped; float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; - glm::vec3 _thrust; + glm::vec3 _thrust; // final acceleration for the current frame bool _isThrustOn; float _thrustMultiplier; + glm::vec3 _moveTarget; glm::vec3 _lastBodyPenetration; int _moveTargetStepCounter; From 203dac054ad734ff630eb7b974f408473d4332af Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 12:19:48 -0700 Subject: [PATCH 47/76] remove unused MoveTarget stuff from MyAvatar --- interface/src/avatar/MyAvatar.cpp | 22 ---------------------- interface/src/avatar/MyAvatar.h | 2 -- 2 files changed, 24 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 33a1127a64..77698ea823 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -62,9 +62,7 @@ MyAvatar::MyAvatar() : _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), - _moveTarget(0,0,0), _lastBodyPenetration(0.0f), - _moveTargetStepCounter(0), _lookAtTargetAvatar(), _shouldRender(true), _billboardValid(false), @@ -98,11 +96,6 @@ void MyAvatar::reset() { setOrientation(glm::quat(glm::vec3(0.0f))); } -void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) { - _moveTarget = moveTarget; - _moveTargetStepCounter = 0; -} - void MyAvatar::update(float deltaTime) { Head* head = getHead(); head->relaxLean(deltaTime); @@ -275,21 +268,6 @@ void MyAvatar::simulate(float deltaTime) { float speed = glm::length(_velocity); _moving = speed > MOVING_SPEED_THRESHOLD; - // If a move target is set, update position explicitly - const float MOVE_FINISHED_TOLERANCE = 0.1f; - const float MOVE_SPEED_FACTOR = 2.0f; - const int MOVE_TARGET_MAX_STEPS = 250; - if ((glm::length(_moveTarget) > EPSILON) && (_moveTargetStepCounter < MOVE_TARGET_MAX_STEPS)) { - if (glm::length(_position - _moveTarget) > MOVE_FINISHED_TOLERANCE) { - _position += (_moveTarget - _position) * (deltaTime * MOVE_SPEED_FACTOR); - _moveTargetStepCounter++; - } else { - // Move completed - _moveTarget = glm::vec3(0,0,0); - _moveTargetStepCounter = 0; - } - } - updateChatCircle(deltaTime); _position += _velocity * deltaTime; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index 592e1172af..ab6181120e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -126,9 +126,7 @@ private: bool _isThrustOn; float _thrustMultiplier; - glm::vec3 _moveTarget; glm::vec3 _lastBodyPenetration; - int _moveTargetStepCounter; QWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; bool _shouldRender; From 141250d51c0a2153461a3f3ce1156c11123ce21e Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 12:22:24 -0700 Subject: [PATCH 48/76] Don't constrain elbow when rotating forearm with wrist. --- interface/src/avatar/SkeletonModel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 4bb7814300..f8ebba676f 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -188,7 +188,8 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector& fingerJoin if (Menu::getInstance()->isOptionChecked(MenuOption::AlignForearmsWithWrists)) { glm::vec3 forearmVector = palmRotation * glm::vec3(sign, 0.0f, 0.0f); setJointPosition(parentJointIndex, palm.getPosition() + forearmVector * - geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale), palmRotation, true); + geometry.joints.at(jointIndex).distanceToParent * extractUniformScale(_scale)); + setJointRotation(parentJointIndex, palmRotation, true); _jointStates[jointIndex].rotation = glm::quat(); } else { From c8c3cf3664ced00de93a0a23d059b7cbbe0c697d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 12:29:01 -0700 Subject: [PATCH 49/76] Remove unused propagate option for applyRotationDelta. --- interface/src/renderer/Model.cpp | 8 +------- interface/src/renderer/Model.h | 2 +- 2 files changed, 2 insertions(+), 8 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 26e59635bb..9c7dc9a6a1 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1026,7 +1026,7 @@ float Model::getLimbLength(int jointIndex) const { return length; } -void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain, bool propagate) { +void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain) { JointState& state = _jointStates[jointIndex]; const FBXGeometry& geometry = _geometry->getFBXGeometry(); const FBXJoint& joint = geometry.joints[jointIndex]; @@ -1042,12 +1042,6 @@ void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool cons glm::quat newRotation = glm::quat(glm::clamp(eulers, joint.rotationMin, joint.rotationMax)); state.combinedRotation = state.combinedRotation * glm::inverse(state.rotation) * newRotation; state.rotation = newRotation; - - if (propagate && targetRotation != state.combinedRotation && - joint.parentIndex != -1 && geometry.joints.at(joint.parentIndex).isFree) { - applyRotationDelta(joint.parentIndex, targetRotation * glm::inverse(state.combinedRotation), true, true); - state.combinedRotation = _jointStates.at(joint.parentIndex).combinedRotation * state.rotation; - } } const int BALL_SUBDIVISIONS = 10; diff --git a/interface/src/renderer/Model.h b/interface/src/renderer/Model.h index 10e9e2a66a..335071d669 100644 --- a/interface/src/renderer/Model.h +++ b/interface/src/renderer/Model.h @@ -257,7 +257,7 @@ protected: /// first free ancestor. float getLimbLength(int jointIndex) const; - void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true, bool propagate = false); + void applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain = true); private: From 2bac8024079ce096462acaf8538c67aaf3bc9815 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Wed, 23 Apr 2014 12:30:39 -0700 Subject: [PATCH 50/76] One more unused variable. --- interface/src/renderer/Model.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/renderer/Model.cpp b/interface/src/renderer/Model.cpp index 9c7dc9a6a1..3484ac5fc8 100644 --- a/interface/src/renderer/Model.cpp +++ b/interface/src/renderer/Model.cpp @@ -1028,8 +1028,7 @@ float Model::getLimbLength(int jointIndex) const { void Model::applyRotationDelta(int jointIndex, const glm::quat& delta, bool constrain) { JointState& state = _jointStates[jointIndex]; - const FBXGeometry& geometry = _geometry->getFBXGeometry(); - const FBXJoint& joint = geometry.joints[jointIndex]; + const FBXJoint& joint = _geometry->getFBXGeometry().joints[jointIndex]; if (!constrain || (joint.rotationMin == glm::vec3(-PI, -PI, -PI) && joint.rotationMax == glm::vec3(PI, PI, PI))) { // no constraints From fe42f66cc9afc856a850ab5944c498a061dae79d Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 13:27:43 -0700 Subject: [PATCH 51/76] change x.f to be x.0f as per the coding standard --- tests/physics/src/ShapeColliderTests.cpp | 112 ++++++++++------------- 1 file changed, 47 insertions(+), 65 deletions(-) diff --git a/tests/physics/src/ShapeColliderTests.cpp b/tests/physics/src/ShapeColliderTests.cpp index fe1d79b456..3f952236e2 100644 --- a/tests/physics/src/ShapeColliderTests.cpp +++ b/tests/physics/src/ShapeColliderTests.cpp @@ -23,18 +23,18 @@ #include "ShapeColliderTests.h" -const glm::vec3 origin(0.f); -static const glm::vec3 xAxis(1.f, 0.f, 0.f); -static const glm::vec3 yAxis(0.f, 1.f, 0.f); -static const glm::vec3 zAxis(0.f, 0.f, 1.f); +const glm::vec3 origin(0.0f); +static const glm::vec3 xAxis(1.0f, 0.0f, 0.0f); +static const glm::vec3 yAxis(0.0f, 1.0f, 0.0f); +static const glm::vec3 zAxis(0.0f, 0.0f, 1.0f); void ShapeColliderTests::sphereMissesSphere() { // non-overlapping spheres of unequal size - float radiusA = 7.f; - float radiusB = 3.f; + float radiusA = 7.0f; + float radiusB = 3.0f; float alpha = 1.2f; float beta = 1.3f; - glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); + glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f)); float offsetDistance = alpha * radiusA + beta * radiusB; SphereShape sphereA(radiusA, origin); @@ -77,13 +77,13 @@ void ShapeColliderTests::sphereMissesSphere() { void ShapeColliderTests::sphereTouchesSphere() { // overlapping spheres of unequal size - float radiusA = 7.f; - float radiusB = 3.f; + float radiusA = 7.0f; + float radiusB = 3.0f; float alpha = 0.2f; float beta = 0.3f; - glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.f, 2.f, 3.f)); + glm::vec3 offsetDirection = glm::normalize(glm::vec3(1.0f, 2.0f, 3.0f)); float offsetDistance = alpha * radiusA + beta * radiusB; - float expectedPenetrationDistance = (1.f - alpha) * radiusA + (1.f - beta) * radiusB; + float expectedPenetrationDistance = (1.0f - alpha) * radiusA + (1.0f - beta) * radiusB; glm::vec3 expectedPenetration = expectedPenetrationDistance * offsetDirection; SphereShape sphereA(radiusA, origin); @@ -118,8 +118,7 @@ void ShapeColliderTests::sphereTouchesSphere() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of sphereA @@ -129,8 +128,7 @@ void ShapeColliderTests::sphereTouchesSphere() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } } @@ -150,8 +148,7 @@ void ShapeColliderTests::sphereTouchesSphere() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of sphereA @@ -161,8 +158,7 @@ void ShapeColliderTests::sphereTouchesSphere() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } } } @@ -181,7 +177,7 @@ void ShapeColliderTests::sphereMissesCapsule() { // give the capsule some arbirary transform float angle = 37.8f; - glm::vec3 axis = glm::normalize( glm::vec3(-7.f, 2.8f, 9.3f) ); + glm::vec3 axis = glm::normalize( glm::vec3(-7.0f, 2.8f, 9.3f) ); glm::quat rotation = glm::angleAxis(angle, axis); glm::vec3 translation(15.1f, -27.1f, -38.6f); capsuleB.setRotation(rotation); @@ -190,7 +186,7 @@ void ShapeColliderTests::sphereMissesCapsule() { CollisionList collisions(16); // walk sphereA along the local yAxis next to, but not touching, capsuleB - glm::vec3 localStartPosition(radialOffset, axialOffset, 0.f); + glm::vec3 localStartPosition(radialOffset, axialOffset, 0.0f); int numberOfSteps = 10; float delta = 1.3f * (totalRadius + halfHeightB) / (numberOfSteps - 1); for (int i = 0; i < numberOfSteps; ++i) { @@ -224,10 +220,10 @@ void ShapeColliderTests::sphereMissesCapsule() { void ShapeColliderTests::sphereTouchesCapsule() { // overlapping sphere and capsule - float radiusA = 2.f; - float radiusB = 1.f; + float radiusA = 2.0f; + float radiusB = 1.0f; float totalRadius = radiusA + radiusB; - float halfHeightB = 2.f; + float halfHeightB = 2.0f; float alpha = 0.5f; float beta = 0.5f; float radialOffset = alpha * radiusA + beta * radiusB; @@ -257,8 +253,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of sphereA @@ -267,8 +262,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } // capsuleB collides with sphereA @@ -288,8 +282,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of capsuleB @@ -300,8 +293,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } } { // sphereA hits end cap at axis @@ -319,13 +311,12 @@ void ShapeColliderTests::sphereTouchesCapsule() { // penetration points from sphereA into capsuleB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); - glm::vec3 expectedPenetration = - ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; + glm::vec3 expectedPenetration = - ((1.0f - alpha) * radiusA + (1.0f - beta) * radiusB) * yAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of sphereA @@ -334,8 +325,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } // capsuleB collides with sphereA @@ -350,13 +340,12 @@ void ShapeColliderTests::sphereTouchesCapsule() { // penetration points from sphereA into capsuleB collision = collisions.getCollision(numCollisions - 1); - expectedPenetration = ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; + expectedPenetration = ((1.0f - alpha) * radiusA + (1.0f - beta) * radiusB) * yAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of capsuleB @@ -367,8 +356,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } } { // sphereA hits start cap at axis @@ -386,13 +374,12 @@ void ShapeColliderTests::sphereTouchesCapsule() { // penetration points from sphereA into capsuleB CollisionInfo* collision = collisions.getCollision(numCollisions - 1); - glm::vec3 expectedPenetration = ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; + glm::vec3 expectedPenetration = ((1.0f - alpha) * radiusA + (1.0f - beta) * radiusB) * yAxis; float inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of sphereA @@ -401,8 +388,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } // capsuleB collides with sphereA @@ -417,13 +403,12 @@ void ShapeColliderTests::sphereTouchesCapsule() { // penetration points from sphereA into capsuleB collision = collisions.getCollision(numCollisions - 1); - expectedPenetration = - ((1.f - alpha) * radiusA + (1.f - beta) * radiusB) * yAxis; + expectedPenetration = - ((1.0f - alpha) * radiusA + (1.0f - beta) * radiusB) * yAxis; inaccuracy = glm::length(collision->_penetration - expectedPenetration); if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } // contactPoint is on surface of capsuleB @@ -434,8 +419,7 @@ void ShapeColliderTests::sphereTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } } if (collisions.size() != numCollisions) { @@ -447,10 +431,10 @@ void ShapeColliderTests::sphereTouchesCapsule() { void ShapeColliderTests::capsuleMissesCapsule() { // non-overlapping capsules - float radiusA = 2.f; - float halfHeightA = 3.f; - float radiusB = 3.f; - float halfHeightB = 4.f; + float radiusA = 2.0f; + float halfHeightA = 3.0f; + float radiusB = 3.0f; + float halfHeightB = 4.0f; float totalRadius = radiusA + radiusB; float totalHalfLength = totalRadius + halfHeightA + halfHeightB; @@ -516,10 +500,10 @@ void ShapeColliderTests::capsuleMissesCapsule() { void ShapeColliderTests::capsuleTouchesCapsule() { // overlapping capsules - float radiusA = 2.f; - float halfHeightA = 3.f; - float radiusB = 3.f; - float halfHeightB = 4.f; + float radiusA = 2.0f; + float halfHeightA = 3.0f; + float radiusB = 3.0f; + float halfHeightB = 4.0f; float totalRadius = radiusA + radiusB; float totalHalfLength = totalRadius + halfHeightA + halfHeightB; @@ -617,8 +601,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad penetration: expected = " << expectedPenetration - << " actual = " << collision->_penetration - << std::endl; + << " actual = " << collision->_penetration; } glm::vec3 expectedContactPoint = capsuleA.getPosition() + radiusA * xAxis; @@ -626,8 +609,7 @@ void ShapeColliderTests::capsuleTouchesCapsule() { if (fabs(inaccuracy) > EPSILON) { std::cout << __FILE__ << ":" << __LINE__ << " ERROR: bad contactPoint: expected = " << expectedContactPoint - << " actual = " << collision->_contactPoint - << std::endl; + << " actual = " << collision->_contactPoint; } // capsuleB vs capsuleA @@ -706,7 +688,7 @@ void ShapeColliderTests::sphereTouchesAACube() { float cubeSide = 2.0f; float sphereRadius = 1.0f; - glm::vec3 sphereCenter(0.f); + glm::vec3 sphereCenter(0.0f); SphereShape sphere(sphereRadius, sphereCenter); float sphereOffset = (0.5f * cubeSide + sphereRadius - 0.25f); From c5f1a8abd67228477dc90a361f55f47b542d23c9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 13:37:13 -0700 Subject: [PATCH 52/76] formatting --- libraries/octree/src/Octree.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index 06db337b70..ebfb954bd8 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -759,9 +759,7 @@ bool Octree::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end bool Octree::findShapeCollisions(const Shape* shape, CollisionList& collisions, Octree::lockType lockType) { - ShapeArgs args = { shape, - collisions, - false }; + ShapeArgs args = { shape, collisions, false }; bool gotLock = false; if (lockType == Octree::Lock) { From 96ca53740008bf025f7781de87d12a9c86035c6e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 13:44:25 -0700 Subject: [PATCH 53/76] removing unused motion-state timers --- interface/src/avatar/MyAvatar.cpp | 15 --------------- interface/src/avatar/MyAvatar.h | 3 --- 2 files changed, 18 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 77698ea823..1de9b74c89 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -54,9 +54,6 @@ MyAvatar::MyAvatar() : _shouldJump(false), _gravity(0.0f, -1.0f, 0.0f), _distanceToNearestAvatar(std::numeric_limits::max()), - _elapsedTimeMoving(0.0f), - _elapsedTimeStopped(0.0f), - _elapsedTimeSinceCollision(0.0f), _lastCollisionPosition(0, 0, 0), _speedBrakes(false), _thrust(0.0f), @@ -139,17 +136,6 @@ void MyAvatar::simulate(float deltaTime) { glm::quat orientation = getOrientation(); - // Update movement timers - _elapsedTimeSinceCollision += deltaTime; - const float VELOCITY_MOVEMENT_TIMER_THRESHOLD = 0.2f; - if (glm::length(_velocity) < VELOCITY_MOVEMENT_TIMER_THRESHOLD) { - _elapsedTimeMoving = 0.0f; - _elapsedTimeStopped += deltaTime; - } else { - _elapsedTimeStopped = 0.0f; - _elapsedTimeMoving += deltaTime; - } - if (_scale != _targetScale) { float scale = (1.0f - SMOOTHING_RATIO) * _scale + SMOOTHING_RATIO * _targetScale; setScale(scale); @@ -798,7 +784,6 @@ void MyAvatar::applyHardCollision(const glm::vec3& penetration, float elasticity // cancel out the velocity component in the direction of penetration float penetrationLength = glm::length(penetration); if (penetrationLength > EPSILON) { - _elapsedTimeSinceCollision = 0.0f; glm::vec3 direction = penetration / penetrationLength; _velocity -= glm::dot(_velocity, direction) * direction * (1.0f + elasticity); _velocity *= glm::clamp(1.0f - damping, 0.0f, 1.0f); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index ab6181120e..b713f1c223 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -117,9 +117,6 @@ private: float _distanceToNearestAvatar; // How close is the nearest avatar? // motion stuff - float _elapsedTimeMoving; // Timers to drive camera transitions when moving - float _elapsedTimeStopped; - float _elapsedTimeSinceCollision; glm::vec3 _lastCollisionPosition; bool _speedBrakes; glm::vec3 _thrust; // final acceleration for the current frame From 10265a4a3e0d48fdccd66eb23059bdd1f2896905 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 23 Apr 2014 14:37:24 -0700 Subject: [PATCH 54/76] temp disable of screen flash for avatar collisions --- interface/src/avatar/MyAvatar.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1de9b74c89..17ff79c443 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -820,7 +820,7 @@ void MyAvatar::updateCollisionSound(const glm::vec3 &penetration, float deltaTim std::min(COLLISION_LOUDNESS * velocityTowardCollision, 1.0f), frequency * (1.0f + velocityTangentToCollision / velocityTowardCollision), std::min(velocityTangentToCollision / velocityTowardCollision * NOISE_SCALING, 1.0f), - 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, true); + 1.0f - DURATION_SCALING * powf(frequency, 0.5f) / velocityTowardCollision, false); } } From b0e1eab7ed19b1967d9514d8d35495024b3ea863 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 23 Apr 2014 16:15:51 -0700 Subject: [PATCH 55/76] Fix chat input textbox to use native scrollbar The border around the textedit was causing QT to use a non-native scrollbar. Moving the box into a frame that contains the border styling fixes this. --- interface/ui/chatWindow.ui | 85 ++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 21 deletions(-) diff --git a/interface/ui/chatWindow.ui b/interface/ui/chatWindow.ui index b1448091c4..4d223b2665 100644 --- a/interface/ui/chatWindow.ui +++ b/interface/ui/chatWindow.ui @@ -186,9 +186,9 @@ QPushButton:pressed { - + - + 0 0 @@ -196,33 +196,77 @@ QPushButton:pressed { 0 - 60 + 78 - - - Helvetica,Arial,sans-serif - 14 - - - border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; + #chatFrame { +border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px; +} QFrame::NoFrame - - Qt::ScrollBarAlwaysOff + + QFrame::Raised - - QAbstractScrollArea::AdjustToContents - - - true - - - false + + 0 + + + 0 + + + 0 + + + 0 + + + 0 + + + + + + 0 + 0 + + + + + 0 + 60 + + + + + Helvetica,Arial,sans-serif + 14 + + + + + + + QFrame::NoFrame + + + Qt::ScrollBarAlwaysOff + + + QAbstractScrollArea::AdjustToContents + + + true + + + false + + + + @@ -237,7 +281,6 @@ QPushButton:pressed { - messagePlainTextEdit messagesScrollArea From 9bdcfe6d041fcf192b1e20597e118f6f130a5c79 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 11:01:12 -0700 Subject: [PATCH 56/76] Undo now fully support local subtrees --- examples/editVoxels.js | 2 - libraries/voxels/src/VoxelTree.cpp | 7 + libraries/voxels/src/VoxelTree.h | 1 + libraries/voxels/src/VoxelTreeCommands.cpp | 130 +++++++++++++----- libraries/voxels/src/VoxelTreeCommands.h | 2 - .../voxels/src/VoxelsScriptingInterface.cpp | 36 ++--- 6 files changed, 115 insertions(+), 63 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 12c571b09c..453ac28649 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -1088,7 +1088,6 @@ function keyPressEvent(event) { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - Voxels.eraseVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s); Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); setAudioPosition(); initialVoxelSound.playRandom(); @@ -1394,7 +1393,6 @@ function checkControllers() { if (Vec3.length(Vec3.subtract(fingerTipPosition,lastFingerAddVoxel)) > (FINGERTIP_VOXEL_SIZE / 2)) { newColor = { red: colors[whichColor].red, green: colors[whichColor].green, blue: colors[whichColor].blue }; - Voxels.eraseVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE); Voxels.setVoxel(fingerTipPosition.x, fingerTipPosition.y, fingerTipPosition.z, FINGERTIP_VOXEL_SIZE, newColor.red, newColor.green, newColor.blue); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index 3a77382a84..aeb877ef78 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -45,6 +45,13 @@ VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) cons return static_cast(getOctreeElementAt(x, y, z, s)); } +VoxelTreeElement* VoxelTree::getEnclosingVoxelAt(float x, float y, float z, float s) const { + unsigned char* octalCode = pointToOctalCode(x,y,z,s); + OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); + + return static_cast(node); +} + void VoxelTree::createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive) { diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index e0bc1d9a47..2992815787 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -30,6 +30,7 @@ public: void deleteVoxelAt(float x, float y, float z, float s); VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const; + VoxelTreeElement* getEnclosingVoxelAt(float x, float y, float z, float s) const; void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive = false); diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index 46837aa23e..d1dc0f3560 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -13,22 +13,56 @@ #include "VoxelTreeCommands.h" + + +struct SendVoxelsOperationArgs { + const unsigned char* newBaseOctCode; + VoxelEditPacketSender* packetSender; +}; + +bool sendVoxelsOperation(OctreeElement* element, void* extraData) { + VoxelTreeElement* voxel = (VoxelTreeElement*)element; + SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; + if (voxel->isColored()) { + const unsigned char* nodeOctalCode = voxel->getOctalCode(); + unsigned char* codeColorBuffer = NULL; + int codeLength = 0; + int bytesInCode = 0; + int codeAndColorLength; + + // If the newBase is NULL, then don't rebase + if (args->newBaseOctCode) { + codeColorBuffer = rebaseOctalCode(nodeOctalCode, args->newBaseOctCode, true); + codeLength = numberOfThreeBitSectionsInCode(codeColorBuffer); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + } else { + codeLength = numberOfThreeBitSectionsInCode(nodeOctalCode); + bytesInCode = bytesRequiredForCodeLength(codeLength); + codeAndColorLength = bytesInCode + SIZE_OF_COLOR_DATA; + codeColorBuffer = new unsigned char[codeAndColorLength]; + memcpy(codeColorBuffer, nodeOctalCode, bytesInCode); + } + + // copy the colors over + codeColorBuffer[bytesInCode + RED_INDEX] = voxel->getColor()[RED_INDEX]; + codeColorBuffer[bytesInCode + GREEN_INDEX] = voxel->getColor()[GREEN_INDEX]; + codeColorBuffer[bytesInCode + BLUE_INDEX] = voxel->getColor()[BLUE_INDEX]; + args->packetSender->queueVoxelEditMessage(PacketTypeVoxelSetDestructive, + codeColorBuffer, codeAndColorLength); + + delete[] codeColorBuffer; + } + return true; // keep going +} + + AddVoxelCommand::AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender, QUndoCommand* parent) : QUndoCommand("Add Voxel", parent), _tree(tree), _packetSender(packetSender), - _voxel(voxel), - _oldTree(NULL) + _voxel(voxel) { - VoxelTreeElement* element = _tree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - if (element) { - _oldTree = new VoxelTree(); - _tree->copySubTreeIntoNewTree(element, _oldTree, true); - } -} - -AddVoxelCommand::~AddVoxelCommand() { - delete _oldTree; } void AddVoxelCommand::redo() { @@ -41,18 +75,11 @@ void AddVoxelCommand::redo() { } void AddVoxelCommand::undo() { - if (_oldTree) { - OctreeElement* element = _tree->getOrCreateChildElementAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - qDebug() << "undo(): " << _voxel.x << " " << _voxel.y << " " << _voxel.z << " " << _voxel.s; - _tree->copyFromTreeIntoSubTree(_oldTree, element); - qDebug() << "done"; - } else { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } @@ -63,6 +90,26 @@ DeleteVoxelCommand::DeleteVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, Voxe _voxel(voxel), _oldTree(NULL) { + _tree->lockForRead(); + VoxelTreeElement* element = _tree->getEnclosingVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element->getScale() == _voxel.s) { + if (!element->hasContent() && !element->isLeaf()) { + _oldTree = new VoxelTree(); + _tree->copySubTreeIntoNewTree(element, _oldTree, false); + } else { + _voxel.red = element->getColor()[0]; + _voxel.green = element->getColor()[1]; + _voxel.blue = element->getColor()[2]; + } + } else if (element->hasContent() && element->isLeaf()) { + _voxel.red = element->getColor()[0]; + _voxel.green = element->getColor()[1]; + _voxel.blue = element->getColor()[2]; + } else { + _voxel.s = 0.0f; + qDebug() << "No element for delete."; + } + _tree->unlock(); } DeleteVoxelCommand::~DeleteVoxelCommand() { @@ -70,21 +117,38 @@ DeleteVoxelCommand::~DeleteVoxelCommand() { } void DeleteVoxelCommand::redo() { - if (_oldTree) { - - } else { - if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); - } - if (_packetSender) { - _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); - } + if (_voxel.s == 0) { + return; + } + + if (_tree) { + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); } + if (_packetSender) { + _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } void DeleteVoxelCommand::undo() { + if (_voxel.s == 0) { + return; + } + if (_oldTree) { - + VoxelTreeElement* element = _oldTree->getVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + if (element) { + if (_tree) { + _tree->lockForWrite(); + _oldTree->copySubTreeIntoNewTree(element, _tree, false); + _tree->unlock(); + } + if (_packetSender) { + SendVoxelsOperationArgs args; + args.newBaseOctCode = NULL; + args.packetSender = _packetSender; + _oldTree->recurseTreeWithOperation(sendVoxelsOperation, &args); + _packetSender->releaseQueuedMessages(); + } + } } else { if (_tree) { _tree->createVoxel(_voxel.x, _voxel.y, _voxel.z, _voxel.s, _voxel.red, _voxel.green, _voxel.blue); diff --git a/libraries/voxels/src/VoxelTreeCommands.h b/libraries/voxels/src/VoxelTreeCommands.h index c3b23e7201..8df1f0dc14 100644 --- a/libraries/voxels/src/VoxelTreeCommands.h +++ b/libraries/voxels/src/VoxelTreeCommands.h @@ -23,7 +23,6 @@ class VoxelTree; class AddVoxelCommand : public QUndoCommand { public: AddVoxelCommand(VoxelTree* tree, VoxelDetail& voxel, VoxelEditPacketSender* packetSender = NULL, QUndoCommand* parent = NULL); - ~AddVoxelCommand(); virtual void redo(); virtual void undo(); @@ -32,7 +31,6 @@ private: VoxelTree* _tree; VoxelEditPacketSender* _packetSender; VoxelDetail _voxel; - VoxelTree* _oldTree; }; class DeleteVoxelCommand : public QUndoCommand { diff --git a/libraries/voxels/src/VoxelsScriptingInterface.cpp b/libraries/voxels/src/VoxelsScriptingInterface.cpp index 08dcfd3f47..15503db454 100644 --- a/libraries/voxels/src/VoxelsScriptingInterface.cpp +++ b/libraries/voxels/src/VoxelsScriptingInterface.cpp @@ -76,32 +76,16 @@ void VoxelsScriptingInterface::setVoxel(float x, float y, float z, float scale, if (_tree) { if (_undoStack) { AddVoxelCommand* addCommand = new AddVoxelCommand(_tree, - addVoxelDetail, - getVoxelPacketSender()); - - VoxelTreeElement* deleteVoxelElement = _tree->getVoxelAt(addVoxelDetail.x, addVoxelDetail.y, addVoxelDetail.z, addVoxelDetail.s); - if (deleteVoxelElement) { - nodeColor color; - memcpy(&color, &deleteVoxelElement->getColor(), sizeof(nodeColor)); - VoxelDetail deleteVoxelDetail = {addVoxelDetail.x, - addVoxelDetail.y, - addVoxelDetail.z, - addVoxelDetail.s, - color[0], - color[1], - color[2]}; - DeleteVoxelCommand* delCommand = new DeleteVoxelCommand(_tree, - deleteVoxelDetail, - getVoxelPacketSender()); - _undoStack->beginMacro(addCommand->text()); - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(delCommand); - _undoStack->push(addCommand); - _undoStack->endMacro(); - } else { - // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. - _undoStack->push(addCommand); - } + addVoxelDetail, + getVoxelPacketSender()); + DeleteVoxelCommand* deleteCommand = new DeleteVoxelCommand(_tree, + addVoxelDetail, + getVoxelPacketSender()); + _undoStack->beginMacro(addCommand->text()); + // As QUndoStack automatically executes redo() on push, we don't need to execute the command ourselves. + _undoStack->push(deleteCommand); + _undoStack->push(addCommand); + _undoStack->endMacro(); } else { // queue the destructive add queueVoxelAdd(PacketTypeVoxelSetDestructive, addVoxelDetail); From f07a418a2708a19dc69c9583aa9c7cd2123c3453 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 11:07:49 -0700 Subject: [PATCH 57/76] namechange CollisionFlags --> CollisionGroups --- interface/src/Menu.cpp | 10 +++++----- interface/src/avatar/Avatar.cpp | 16 ++++++++-------- interface/src/avatar/Avatar.h | 4 ++-- interface/src/avatar/MyAvatar.cpp | 18 +++++++----------- 4 files changed, 22 insertions(+), 26 deletions(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 84b17fddca..74df3e4f63 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -505,7 +505,7 @@ void Menu::loadSettings(QSettings* settings) { // MyAvatar caches some menu options, so we have to update them whenever we load settings. // TODO: cache more settings in MyAvatar that are checked with very high frequency. MyAvatar* myAvatar = Application::getInstance()->getAvatar(); - myAvatar->updateCollisionFlags(); + myAvatar->updateCollisionGroups(); if (lockedSettings) { Application::getInstance()->unlockSettings(); @@ -1368,13 +1368,13 @@ void Menu::addAvatarCollisionSubMenu(QMenu* overMenu) { Application* appInstance = Application::getInstance(); QObject* avatar = appInstance->getAvatar(); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithEnvironment, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithAvatars, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithVoxels, - 0, false, avatar, SLOT(updateCollisionFlags())); + 0, false, avatar, SLOT(updateCollisionGroups())); addCheckableActionToQMenuAndActionHash(subMenu, MenuOption::CollideWithParticles, - 0, true, avatar, SLOT(updateCollisionFlags())); + 0, true, avatar, SLOT(updateCollisionGroups())); } QAction* Menu::getActionFromName(const QString& menuName, QMenu* menu) { diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 2df1fd2302..b060c3421a 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -54,7 +54,7 @@ Avatar::Avatar() : _mouseRayOrigin(0.0f, 0.0f, 0.0f), _mouseRayDirection(0.0f, 0.0f, 0.0f), _moving(false), - _collisionFlags(0), + _collisionGroups(0), _initialized(false), _shouldRenderBillboard(true) { @@ -550,7 +550,7 @@ bool Avatar::findCollisions(const QVector& shapes, CollisionList& } bool Avatar::findParticleCollisions(const glm::vec3& particleCenter, float particleRadius, CollisionList& collisions) { - if (_collisionFlags & COLLISION_GROUP_PARTICLES) { + if (_collisionGroups & COLLISION_GROUP_PARTICLES) { return false; } bool collided = false; @@ -740,19 +740,19 @@ void Avatar::renderJointConnectingCone(glm::vec3 position1, glm::vec3 position2, glEnd(); } -void Avatar::updateCollisionFlags() { - _collisionFlags = 0; +void Avatar::updateCollisionGroups() { + _collisionGroups = 0; if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithEnvironment)) { - _collisionFlags |= COLLISION_GROUP_ENVIRONMENT; + _collisionGroups |= COLLISION_GROUP_ENVIRONMENT; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithAvatars)) { - _collisionFlags |= COLLISION_GROUP_AVATARS; + _collisionGroups |= COLLISION_GROUP_AVATARS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithVoxels)) { - _collisionFlags |= COLLISION_GROUP_VOXELS; + _collisionGroups |= COLLISION_GROUP_VOXELS; } if (Menu::getInstance()->isOptionChecked(MenuOption::CollideWithParticles)) { - _collisionFlags |= COLLISION_GROUP_PARTICLES; + _collisionGroups |= COLLISION_GROUP_PARTICLES; } } diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 805a60d425..6106b9f39c 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -149,7 +149,7 @@ public: void updateShapePositions(); public slots: - void updateCollisionFlags(); + void updateCollisionGroups(); signals: void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision); @@ -166,7 +166,7 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - uint32_t _collisionFlags; + uint32_t _collisionGroups; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 17ff79c443..9f70f41631 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -284,7 +284,7 @@ void MyAvatar::simulate(float deltaTime) { _thrust *= glm::vec3(0.0f); // now that we're done stepping the avatar forward in time, compute new collisions - if (_collisionFlags != 0) { + if (_collisionGroups != 0) { Camera* myCamera = Application::getInstance()->getCamera(); float radius = getSkeletonHeight() * COLLISION_RADIUS_SCALE; @@ -292,15 +292,15 @@ void MyAvatar::simulate(float deltaTime) { radius = myCamera->getAspectRatio() * (myCamera->getNearClip() / cos(myCamera->getFieldOfView() / 2.0f)); radius *= COLLISION_RADIUS_SCALAR; } - if (_collisionFlags) { + if (_collisionGroups) { updateShapePositions(); - if (_collisionFlags & COLLISION_GROUP_ENVIRONMENT) { + if (_collisionGroups & COLLISION_GROUP_ENVIRONMENT) { updateCollisionWithEnvironment(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_VOXELS) { + if (_collisionGroups & COLLISION_GROUP_VOXELS) { updateCollisionWithVoxels(deltaTime, radius); } - if (_collisionFlags & COLLISION_GROUP_AVATARS) { + if (_collisionGroups & COLLISION_GROUP_AVATARS) { updateCollisionWithAvatars(deltaTime); } } @@ -408,17 +408,13 @@ void MyAvatar::renderDebugBodyPoints() { glTranslatef(position.x, position.y, position.z); glutSolidSphere(0.15, 10, 10); glPopMatrix(); - - } // virtual void MyAvatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) { - // don't render if we've been asked to disable local rendering - if (!_shouldRender) { - return; // exit early + if (_shouldRender) { + Avatar::render(cameraPosition, renderMode); } - Avatar::render(cameraPosition, renderMode); } void MyAvatar::renderHeadMouse() const { From 1844eb2c9e7302ba8835fd2ae091617894ab6f7a Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 11:12:01 -0700 Subject: [PATCH 58/76] Pre CR tweaks --- libraries/voxels/src/VoxelTreeCommands.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index d1dc0f3560..a35096b5c7 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -21,7 +21,7 @@ struct SendVoxelsOperationArgs { }; bool sendVoxelsOperation(OctreeElement* element, void* extraData) { - VoxelTreeElement* voxel = (VoxelTreeElement*)element; + VoxelTreeElement* voxel = static_cast(element); SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; if (voxel->isColored()) { const unsigned char* nodeOctalCode = voxel->getOctalCode(); @@ -117,19 +117,20 @@ DeleteVoxelCommand::~DeleteVoxelCommand() { } void DeleteVoxelCommand::redo() { - if (_voxel.s == 0) { + if (_voxel.s == 0.0f) { return; } if (_tree) { - _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); } + _tree->deleteVoxelAt(_voxel.x, _voxel.y, _voxel.z, _voxel.s); + } if (_packetSender) { _packetSender->queueVoxelEditMessages(PacketTypeVoxelErase, 1, &_voxel); } } void DeleteVoxelCommand::undo() { - if (_voxel.s == 0) { + if (_voxel.s == 0.0f) { return; } @@ -157,4 +158,4 @@ void DeleteVoxelCommand::undo() { _packetSender->queueVoxelEditMessages(PacketTypeVoxelSet, 1, &_voxel); } } -} \ No newline at end of file +} From 73d0674565038eb80c2782ab01db9a2937cd8d0a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 11:19:08 -0700 Subject: [PATCH 59/76] expose MyAvatar.collisionGroups to JS --- interface/src/avatar/Avatar.h | 6 +++++- libraries/shared/src/CollisionInfo.h | 1 + 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index 6106b9f39c..a1ff817b02 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -63,6 +63,7 @@ class Texture; class Avatar : public AvatarData { Q_OBJECT + Q_PROPERTY(quint32 collisionGroups READ getCollisionGroups WRITE setCollisionGroups) public: Avatar(); @@ -148,6 +149,9 @@ public: virtual float getBoundingRadius() const; void updateShapePositions(); + quint32 getCollisionGroups() const { return _collisionGroups; } + void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } + public slots: void updateCollisionGroups(); @@ -166,7 +170,7 @@ protected: float _stringLength; bool _moving; ///< set when position is changing - uint32_t _collisionGroups; + quint32 _collisionGroups; // protected methods... glm::vec3 getBodyRightDirection() const { return getOrientation() * IDENTITY_RIGHT; } diff --git a/libraries/shared/src/CollisionInfo.h b/libraries/shared/src/CollisionInfo.h index 7db965fe64..510728daa6 100644 --- a/libraries/shared/src/CollisionInfo.h +++ b/libraries/shared/src/CollisionInfo.h @@ -27,6 +27,7 @@ const quint32 COLLISION_GROUP_ENVIRONMENT = 1U << 0; const quint32 COLLISION_GROUP_AVATARS = 1U << 1; const quint32 COLLISION_GROUP_VOXELS = 1U << 2; const quint32 COLLISION_GROUP_PARTICLES = 1U << 3; +const quint32 VALID_COLLISION_GROUPS = 0x0f; // CollisionInfo contains details about the collision between two things: BodyA and BodyB. // The assumption is that the context that analyzes the collision knows about BodyA but From ad0f0118bcb879f7f2534ef597d9d306b0b9b6f4 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 15:01:37 -0600 Subject: [PATCH 60/76] fixes for new versioning: --- interface/src/Application.cpp | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4adb2f772a..4d9c70aeda 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3520,10 +3520,9 @@ void Application::parseVersionXml() { QString operatingSystem("ubuntu"); #endif - QString releaseDate; - QString releaseNotes; QString latestVersion; QUrl downloadUrl; + QString releaseNotes("Unavailable"); QObject* sender = QObject::sender(); QXmlStreamReader xml(qobject_cast(sender)); @@ -3531,21 +3530,15 @@ void Application::parseVersionXml() { QXmlStreamReader::TokenType token = xml.readNext(); if (token == QXmlStreamReader::StartElement) { - if (xml.name() == "ReleaseDate") { - xml.readNext(); - releaseDate = xml.text().toString(); - } - if (xml.name() == "ReleaseNotes") { - xml.readNext(); - releaseNotes = xml.text().toString(); - } - if (xml.name() == "Version") { - xml.readNext(); - latestVersion = xml.text().toString(); - } + xml.readNext(); if (xml.name() == operatingSystem) { xml.readNext(); - downloadUrl = QUrl(xml.text().toString()); + if (xml.name() == "version") { + latestVersion = xml.text().toString(); + } + if (xml.name() == "url") { + downloadUrl = xml.text().toString(); + } } } } From 27002a94069b5ec13fecd49c12aada8c83ce7318 Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 15:10:37 -0600 Subject: [PATCH 61/76] Casting to QUrl --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 4d9c70aeda..20cab975a4 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3537,7 +3537,7 @@ void Application::parseVersionXml() { latestVersion = xml.text().toString(); } if (xml.name() == "url") { - downloadUrl = xml.text().toString(); + downloadUrl = QUrl(xml.text().toString()); } } } From 0a7a5031ee05b6ca657cc82109e0abd5f9c11c78 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 14:17:10 -0700 Subject: [PATCH 62/76] expose COLLISION_GOUP_* constants to JS --- libraries/script-engine/src/ScriptEngine.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 2e92567fe7..b923427307 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -230,8 +231,13 @@ void ScriptEngine::init() { registerGlobalObject("Voxels", &_voxelsScriptingInterface); - QScriptValue treeScaleValue = _engine.newVariant(QVariant(TREE_SCALE)); - _engine.globalObject().setProperty("TREE_SCALE", treeScaleValue); + // constants + QScriptValue globalObject = _engine.globalObject(); + globalObject.setProperty("TREE_SCALE", _engine.newVariant(QVariant(TREE_SCALE))); + globalObject.setProperty("COLLISION_GROUP_ENVIRONMENT", _engine.newVariant(QVariant(COLLISION_GROUP_ENVIRONMENT))); + globalObject.setProperty("COLLISION_GROUP_AVATARS", _engine.newVariant(QVariant(COLLISION_GROUP_AVATARS))); + globalObject.setProperty("COLLISION_GROUP_VOXELS", _engine.newVariant(QVariant(COLLISION_GROUP_VOXELS))); + globalObject.setProperty("COLLISION_GROUP_PARTICLES", _engine.newVariant(QVariant(COLLISION_GROUP_PARTICLES))); // let the VoxelPacketSender know how frequently we plan to call it _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(SCRIPT_DATA_CALLBACK_USECS); @@ -561,4 +567,4 @@ void ScriptEngine::include(const QString& includeFile) { qDebug() << "Uncaught exception at (" << includeFile << ") line" << line << ":" << result.toString(); emit errorMessage("Uncaught exception at (" + includeFile + ") line" + QString::number(line) + ":" + result.toString()); } -} \ No newline at end of file +} From ccad0aed9e68e993360cbadfb404c6f20bf01001 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:01 -0700 Subject: [PATCH 63/76] Move ChatInputArea code in header to .cpp --- interface/src/ui/ChatInputArea.cpp | 19 +++++++++++++++++++ interface/src/ui/ChatInputArea.h | 7 +++---- 2 files changed, 22 insertions(+), 4 deletions(-) create mode 100644 interface/src/ui/ChatInputArea.cpp diff --git a/interface/src/ui/ChatInputArea.cpp b/interface/src/ui/ChatInputArea.cpp new file mode 100644 index 0000000000..3e8fc84fe2 --- /dev/null +++ b/interface/src/ui/ChatInputArea.cpp @@ -0,0 +1,19 @@ +// +// ChatInputArea.cpp +// interface/src/ui +// +// Created by Ryan Huffman on 4/24/14. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "ChatInputArea.h" + +ChatInputArea::ChatInputArea(QWidget* parent) : QTextEdit(parent) { +}; + +void ChatInputArea::insertFromMimeData(const QMimeData* source) { + insertPlainText(source->text()); +}; diff --git a/interface/src/ui/ChatInputArea.h b/interface/src/ui/ChatInputArea.h index 264a9932c6..31d1584df7 100644 --- a/interface/src/ui/ChatInputArea.h +++ b/interface/src/ui/ChatInputArea.h @@ -13,16 +13,15 @@ #define hifi_ChatInputArea_h #include +#include class ChatInputArea : public QTextEdit { Q_OBJECT public: - ChatInputArea(QWidget* parent) : QTextEdit(parent) { }; + ChatInputArea(QWidget* parent); protected: - void insertFromMimeData(const QMimeData* source) { - insertPlainText(source->text()); - }; + void insertFromMimeData(const QMimeData* source); }; #endif // hifi_ChatInputArea_h From 7b0981202848064059ccbcf691d077612a625aa8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:26 -0700 Subject: [PATCH 64/76] Remove insertFromMimeData override in ChatMessageArea --- interface/src/ui/ChatMessageArea.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/interface/src/ui/ChatMessageArea.h b/interface/src/ui/ChatMessageArea.h index b726a31d76..57199538fd 100644 --- a/interface/src/ui/ChatMessageArea.h +++ b/interface/src/ui/ChatMessageArea.h @@ -32,11 +32,6 @@ signals: protected: virtual void wheelEvent(QWheelEvent* event); bool _useFixedHeight; - - void insertFromMimeData(const QMimeData* source) { - insertPlainText(source->text()); - }; - }; #endif // hifi_ChatMessageArea_h From b69fa73dfae82a38ab52327f9a763698e84b0df8 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 14:54:57 -0700 Subject: [PATCH 65/76] Unsplit a line in FramelessDialog --- interface/src/ui/FramelessDialog.h | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/interface/src/ui/FramelessDialog.h b/interface/src/ui/FramelessDialog.h index 22666cca63..828602a5db 100644 --- a/interface/src/ui/FramelessDialog.h +++ b/interface/src/ui/FramelessDialog.h @@ -21,8 +21,7 @@ class FramelessDialog : public QDialog { public: enum Position { POSITION_LEFT, POSITION_RIGHT }; - FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, - Position position = POSITION_LEFT); + FramelessDialog(QWidget* parent = 0, Qt::WindowFlags flags = 0, Position position = POSITION_LEFT); void setStyleSheetFile(const QString& fileName); protected: From f4c98a8fa4597832a1419107de1487d0e1edf14e Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 16:21:49 -0600 Subject: [PATCH 66/76] Fixing xml parsing --- interface/src/Application.cpp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 20cab975a4..8fdd41ca47 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3526,22 +3526,24 @@ void Application::parseVersionXml() { QObject* sender = QObject::sender(); QXmlStreamReader xml(qobject_cast(sender)); - while (!xml.atEnd() && !xml.hasError()) { - QXmlStreamReader::TokenType token = xml.readNext(); - - if (token == QXmlStreamReader::StartElement) { - xml.readNext(); - if (xml.name() == operatingSystem) { - xml.readNext(); - if (xml.name() == "version") { + + while(!xml.atEnd() && !xml.hasError()) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { + while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") { + xml.readNext(); latestVersion = xml.text().toString(); } - if (xml.name() == "url") { + if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "url") { + xml.readNext(); downloadUrl = QUrl(xml.text().toString()); } + xml.readNext(); } } + xml.readNext(); } + if (!shouldSkipVersion(latestVersion) && applicationVersion() != latestVersion) { new UpdateDialog(_glWidget, releaseNotes, latestVersion, downloadUrl); } From a21991c5c24e36cfcd5089f7247020a43902444d Mon Sep 17 00:00:00 2001 From: Leonardo Murillo Date: Thu, 24 Apr 2014 16:22:34 -0600 Subject: [PATCH 67/76] Fixing xml parsing --- interface/src/Application.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 8fdd41ca47..ab505ede93 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3527,9 +3527,9 @@ void Application::parseVersionXml() { QXmlStreamReader xml(qobject_cast(sender)); - while(!xml.atEnd() && !xml.hasError()) { + while (!xml.atEnd() && !xml.hasError()) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name() == operatingSystem) { - while(!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { + while (!(xml.tokenType() == QXmlStreamReader::EndElement && xml.name() == operatingSystem)) { if (xml.tokenType() == QXmlStreamReader::StartElement && xml.name().toString() == "version") { xml.readNext(); latestVersion = xml.text().toString(); From 0b5c1b0a9a0d82fbd4fa2e0d685c15ad1bf24de8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 15:43:03 -0700 Subject: [PATCH 68/76] add MyAvatar::_motionBehaviors (for obeyGravity) Also reconcile Menu checkable set vs script-set collision groups. --- interface/src/Application.cpp | 2 +- interface/src/Menu.cpp | 6 +++--- interface/src/Menu.h | 2 +- interface/src/avatar/Avatar.h | 2 +- interface/src/avatar/MyAvatar.cpp | 26 ++++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 11 +++++++++++ 6 files changed, 41 insertions(+), 8 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 3ae4720351..e9c208bace 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -861,7 +861,7 @@ void Application::keyPressEvent(QKeyEvent* event) { case Qt::Key_G: if (isShifted) { - Menu::getInstance()->triggerOption(MenuOption::Gravity); + Menu::getInstance()->triggerOption(MenuOption::ObeyGravity); } break; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 74df3e4f63..4aeb4dd203 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -186,9 +186,9 @@ Menu::Menu() : QAction::PreferencesRole); addDisabledActionAndSeparator(editMenu, "Physics"); - addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::Gravity, Qt::SHIFT | Qt::Key_G, false); - - + QObject* avatar = appInstance->getAvatar(); + addCheckableActionToQMenuAndActionHash(editMenu, MenuOption::ObeyGravity, Qt::SHIFT | Qt::Key_G, true, + avatar, SLOT(updateMotionBehaviorFlags())); addAvatarCollisionSubMenu(editMenu); diff --git a/interface/src/Menu.h b/interface/src/Menu.h index a1e6cded2a..8b2368d22f 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -313,7 +313,7 @@ namespace MenuOption { const QString GoTo = "Go To..."; const QString GoToDomain = "Go To Domain..."; const QString GoToLocation = "Go To Location..."; - const QString Gravity = "Use Gravity"; + const QString ObeyGravity = "Obey Gravity"; const QString HandsCollideWithSelf = "Collide With Self"; const QString HeadMouse = "Head Mouse"; const QString IncreaseAvatarSize = "Increase Avatar Size"; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index a1ff817b02..bcf3487e09 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -150,7 +150,7 @@ public: void updateShapePositions(); quint32 getCollisionGroups() const { return _collisionGroups; } - void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } + virtual void setCollisionGroups(quint32 collisionGroups) { _collisionGroups = (collisionGroups & VALID_COLLISION_GROUPS); } public slots: void updateCollisionGroups(); diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 9f70f41631..467b1f2613 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -59,6 +59,7 @@ MyAvatar::MyAvatar() : _thrust(0.0f), _isThrustOn(false), _thrustMultiplier(1.0f), + _motionBehaviors(0), _lastBodyPenetration(0.0f), _lookAtTargetAvatar(), _shouldRender(true), @@ -123,7 +124,7 @@ void MyAvatar::update(float deltaTime) { head->setAudioLoudness(audio->getLastInputLoudness()); head->setAudioAverageLoudness(audio->getAudioAverageInputLoudness()); - if (Menu::getInstance()->isOptionChecked(MenuOption::Gravity)) { + if (_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY) { setGravity(Application::getInstance()->getEnvironment()->getGravity(getPosition())); } else { setGravity(glm::vec3(0.0f, 0.0f, 0.0f)); @@ -1134,7 +1135,28 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { setPosition(newPosition); emit transformChanged(); } - +} + +void MyAvatar::updateMotionBehaviors() { + _motionBehaviors = 0; + if (Menu::getInstance()->isOptionChecked(MenuOption::ObeyGravity)) { + _motionBehaviors |= AVATAR_MOTION_OBEY_GRAVITY; + } +} + +void MyAvatar::setCollisionGroups(quint32 collisionGroups) { + Avatar::setCollisionGroups(collisionGroups & VALID_COLLISION_GROUPS); + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::CollideWithEnvironment, (bool)(_collisionGroups & COLLISION_GROUP_ENVIRONMENT)); + menu->setIsOptionChecked(MenuOption::CollideWithAvatars, (bool)(_collisionGroups & COLLISION_GROUP_AVATARS)); + menu->setIsOptionChecked(MenuOption::CollideWithVoxels, (bool)(_collisionGroups & COLLISION_GROUP_VOXELS)); + menu->setIsOptionChecked(MenuOption::CollideWithParticles, (bool)(_collisionGroups & COLLISION_GROUP_PARTICLES)); +} + +void MyAvatar::setMotionBehaviors(quint32 flags) { + _motionBehaviors = flags; + Menu* menu = Menu::getInstance(); + menu->setIsOptionChecked(MenuOption::ObeyGravity, (bool)(_motionBehaviors & AVATAR_MOTION_OBEY_GRAVITY)); } void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index b713f1c223..9b6b13568f 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -25,9 +25,12 @@ enum AvatarHandState NUM_HAND_STATES }; +const quint32 AVATAR_MOTION_OBEY_GRAVITY = 1U << 0; + class MyAvatar : public Avatar { Q_OBJECT Q_PROPERTY(bool shouldRenderLocally READ getShouldRenderLocally WRITE setShouldRenderLocally) + Q_PROPERTY(quint32 motionBehaviors READ getMotionBehaviors WRITE setMotionBehaviors) public: MyAvatar(); @@ -88,6 +91,10 @@ public: virtual void setFaceModelURL(const QUrl& faceModelURL); virtual void setSkeletonModelURL(const QUrl& skeletonModelURL); + virtual void setCollisionGroups(quint32 collisionGroups); + void setMotionBehaviors(quint32 flags); + quint32 getMotionBehaviors() const { return _motionBehaviors; } + void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration); public slots: @@ -104,6 +111,8 @@ public slots: glm::vec3 getThrust() { return _thrust; }; void setThrust(glm::vec3 newThrust) { _thrust = newThrust; } + void updateMotionBehaviors(); + signals: void transformChanged(); @@ -123,6 +132,8 @@ private: bool _isThrustOn; float _thrustMultiplier; + quint32 _motionBehaviors; + glm::vec3 _lastBodyPenetration; QWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; From d88897ccc707be1e2624c951ae41adcc2d48bd4e Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Thu, 24 Apr 2014 15:55:34 -0700 Subject: [PATCH 69/76] Add error box when going to user/location that doesn't exist --- interface/src/Application.h | 1 + interface/src/avatar/MyAvatar.cpp | 3 +++ interface/src/location/LocationManager.cpp | 4 ++++ 3 files changed, 8 insertions(+) diff --git a/interface/src/Application.h b/interface/src/Application.h index fb48acb721..6bb2bf4c81 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 317f408aa7..b8a45aacd5 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -12,6 +12,7 @@ #include #include +#include #include #include @@ -1178,6 +1179,8 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) { coordinateItems[2].toFloat()) - newOrientation * IDENTITY_FRONT * DISTANCE_TO_USER; setPosition(newPosition); emit transformChanged(); + } else { + QMessageBox::warning(Application::getInstance()->getWindow(), "", "That user or location could not be found."); } } diff --git a/interface/src/location/LocationManager.cpp b/interface/src/location/LocationManager.cpp index 8009551b6c..f80c331df4 100644 --- a/interface/src/location/LocationManager.cpp +++ b/interface/src/location/LocationManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "Application.h" #include "LocationManager.h" @@ -118,6 +120,8 @@ void LocationManager::checkForMultipleDestinations() { Application::getInstance()->getAvatar()->goToLocationFromResponse(_placeData); return; } + + QMessageBox::warning(Application::getInstance()->getWindow(), "", "That user or location could not be found."); } } From 01637e80377b43f84ce08d5faf714d7715fe0ba0 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 17:37:48 -0700 Subject: [PATCH 70/76] Fix error introduced with gettimeofday removing + spelling mistake --- interface/src/Audio.cpp | 6 +++--- interface/src/Audio.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index c182f6e842..68e38615bf 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -644,10 +644,10 @@ void Audio::addReceivedAudioToBuffer(const QByteArray& audioByteArray) { const int NUM_INITIAL_PACKETS_DISCARD = 3; const int STANDARD_DEVIATION_SAMPLE_COUNT = 500; - _timeSinceLastRecieved.start(); _totalPacketsReceived++; - double timeDiff = (double)_timeSinceLastRecieved.nsecsElapsed() / 1000000.0; // ns to ms + double timeDiff = (double)_timeSinceLastReceived.nsecsElapsed() / 1000000.0; // ns to ms + _timeSinceLastReceived.start(); // Discard first few received packets for computing jitter (often they pile up on start) if (_totalPacketsReceived > NUM_INITIAL_PACKETS_DISCARD) { @@ -1265,7 +1265,7 @@ bool Audio::switchOutputToAudioDevice(const QAudioDeviceInfo& outputDeviceInfo) // setup a procedural audio output device _proceduralAudioOutput = new QAudioOutput(outputDeviceInfo, _outputFormat, this); - _timeSinceLastRecieved.start(); + _timeSinceLastReceived.start(); // setup spatial audio ringbuffer int numFrameSamples = _outputFormat.sampleRate() * _desiredOutputFormat.channelCount(); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index e1b8a7dddc..277c606d4b 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -129,7 +129,7 @@ private: QString _outputAudioDeviceName; StDev _stdev; - QElapsedTimer _timeSinceLastRecieved; + QElapsedTimer _timeSinceLastReceived; float _averagedLatency; float _measuredJitter; int16_t _jitterBufferSamples; From cf7fe2306bafa1c2710ba7942c1fff19c4931277 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 24 Apr 2014 18:10:51 -0700 Subject: [PATCH 71/76] Fix audio jitter --- interface/src/ui/PreferencesDialog.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 550c616fc1..7a70b743bd 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -184,6 +184,7 @@ void PreferencesDialog::savePreferences() { Menu::getInstance()->setMaxVoxelPacketsPerSecond(ui.maxVoxelsPPSSpin->value()); Menu::getInstance()->setAudioJitterBufferSamples(ui.audioJitterSpin->value()); + Application::getInstance()->getAudio()->setJitterBufferSamples(ui.audioJitterSpin->value()); Application::getInstance()->resizeGL(Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height()); From afb12bcd70f1a388822ca4d54c4d3dfd5d339e71 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 24 Apr 2014 19:12:23 -0700 Subject: [PATCH 72/76] add swissArmyJetpack.js --- examples/swissArmyJetpack.js | 142 +++++++++++++++++++++++++++++++++++ 1 file changed, 142 insertions(+) create mode 100644 examples/swissArmyJetpack.js diff --git a/examples/swissArmyJetpack.js b/examples/swissArmyJetpack.js new file mode 100644 index 0000000000..9bb5bea267 --- /dev/null +++ b/examples/swissArmyJetpack.js @@ -0,0 +1,142 @@ +// +// swissArmyJetpack.js +// examples +// +// Created by Andrew Meadows 2014.04.24 +// Copyright 2014 High Fidelity, Inc. +// +// This is a work in progress. It will eventually be able to move the avatar around, +// toggle collision groups, modify avatar movement options, and other stuff (maybe trigger animations). +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var numberOfButtons = 3; + +var enabledColors = new Array(); +enabledColors[0] = { red: 255, green: 0, blue: 0}; +enabledColors[1] = { red: 0, green: 255, blue: 0}; +enabledColors[2] = { red: 0, green: 0, blue: 255}; + +var disabledColors = new Array(); +disabledColors[0] = { red: 90, green: 75, blue: 75}; +disabledColors[1] = { red: 75, green: 90, blue: 75}; +disabledColors[2] = { red: 75, green: 90, blue: 90}; + +var buttons = new Array(); +var labels = new Array(); + +var labelContents = new Array(); +labelContents[0] = "Collide with Avatars"; +labelContents[1] = "Collide with Voxels"; +labelContents[2] = "Collide with Particles"; +var groupBits = 0; + +var buttonStates = new Array(); + +var disabledOffsetT = 0; +var enabledOffsetT = 55; + +var buttonX = 50; +var buttonY = 200; +var buttonWidth = 30; +var buttonHeight = 54; +var textX = buttonX + buttonWidth + 10; + +for (i = 0; i < numberOfButtons; i++) { + var offsetS = 12 + var offsetT = disabledOffsetT; + + buttons[i] = Overlays.addOverlay("image", { + //x: buttonX + (buttonWidth * i), + x: buttonX, + y: buttonY + (buttonHeight * i), + width: buttonWidth, + height: buttonHeight, + subImage: { x: offsetS, y: offsetT, width: buttonWidth, height: buttonHeight }, + imageURL: "http://highfidelity-public.s3-us-west-1.amazonaws.com/images/testing-swatches.svg", + color: disabledColors[i], + alpha: 1, + }); + + labels[i] = Overlays.addOverlay("text", { + x: textX, + y: buttonY + (buttonHeight * i) + 12, + width: 150, + height: 50, + color: { red: 0, green: 0, blue: 0}, + textColor: { red: 255, green: 0, blue: 0}, + topMargin: 4, + leftMargin: 4, + text: labelContents[i] + }); + + buttonStates[i] = false; +} + +function updateButton(i, enabled) { + var offsetY = disabledOffsetT; + var buttonColor = disabledColors[i]; + groupBits + if (enabled) { + offsetY = enabledOffsetT; + buttonColor = enabledColors[i]; + if (i == 0) { + groupBits |= COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits |= COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits |= COLLISION_GROUP_PARTICLES; + } + } else { + if (i == 0) { + groupBits &= ~COLLISION_GROUP_AVATARS; + } else if (i == 1) { + groupBits &= ~COLLISION_GROUP_VOXELS; + } else if (i == 2) { + groupBits &= ~COLLISION_GROUP_PARTICLES; + } + } + MyAvatar.collisionGroups = groupBits; + + Overlays.editOverlay(buttons[i], { subImage: { y: offsetY } } ); + Overlays.editOverlay(buttons[i], { color: buttonColor } ); + buttonStates[i] = enabled; +} + +// When our script shuts down, we should clean up all of our overlays +function scriptEnding() { + for (i = 0; i < numberOfButtons; i++) { + print("adebug deleting overlay " + i); + Overlays.deleteOverlay(buttons[i]); + Overlays.deleteOverlay(labels[i]); + } +} +Script.scriptEnding.connect(scriptEnding); + + +// Our update() function is called at approximately 60fps, and we will use it to animate our various overlays +function update(deltaTime) { + if (groupBits != MyAvatar.collisionGroups) { + groupBits = MyAvatar.collisionGroups; + updateButton(0, groupBits & COLLISION_GROUP_AVATARS); + updateButton(1, groupBits & COLLISION_GROUP_VOXELS); + updateButton(2, groupBits & COLLISION_GROUP_PARTICLES); + } +} +Script.update.connect(update); + + +// we also handle click detection in our mousePressEvent() +function mousePressEvent(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y}); + for (i = 0; i < numberOfButtons; i++) { + if (clickedOverlay == buttons[i]) { + var enabled = !(buttonStates[i]); + updateButton(i, enabled); + } + } +} +Controller.mousePressEvent.connect(mousePressEvent); + From 6acdf9cd6cd98c728a89e249f9bc3743c6845412 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 25 Apr 2014 11:21:02 -0700 Subject: [PATCH 73/76] fix issues with bad timestamps --- libraries/octree/src/OctreeSceneStats.cpp | 39 +++++++++++++++++++---- libraries/shared/src/SharedUtil.cpp | 4 ++- 2 files changed, 36 insertions(+), 7 deletions(-) diff --git a/libraries/octree/src/OctreeSceneStats.cpp b/libraries/octree/src/OctreeSceneStats.cpp index ad8702adc2..e7d34680a7 100644 --- a/libraries/octree/src/OctreeSceneStats.cpp +++ b/libraries/octree/src/OctreeSceneStats.cpp @@ -820,11 +820,7 @@ const char* OctreeSceneStats::getItemValue(Item item) { void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, bool wasStatsPacket, int nodeClockSkewUsec) { - _incomingPacket++; - _incomingBytes += packet.size(); - if (!wasStatsPacket) { - _incomingWastedBytes += (MAX_PACKET_SIZE - packet.size()); - } + const bool wantExtraDebugging = false; int numBytesPacketHeader = numBytesForPacketHeader(packet); const unsigned char* dataAt = reinterpret_cast(packet.data()) + numBytesPacketHeader; @@ -842,12 +838,43 @@ void OctreeSceneStats::trackIncomingOctreePacket(const QByteArray& packet, OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow(); int flightTime = arrivedAt - sentAt + nodeClockSkewUsec; + + if (wantExtraDebugging) { + qDebug() << "sentAt:" << sentAt << " usecs"; + qDebug() << "arrivedAt:" << arrivedAt << " usecs"; + qDebug() << "nodeClockSkewUsec:" << nodeClockSkewUsec << " usecs"; + qDebug() << "flightTime:" << flightTime << " usecs"; + } + + // Guard against possible corrupted packets... with bad timestamps + const int MAX_RESONABLE_FLIGHT_TIME = 200 * USECS_PER_SECOND; // 200 seconds is more than enough time for a packet to arrive + const int MIN_RESONABLE_FLIGHT_TIME = 0; + if (flightTime > MAX_RESONABLE_FLIGHT_TIME || flightTime < MIN_RESONABLE_FLIGHT_TIME) { + qDebug() << "ignoring unreasonable packet... flightTime:" << flightTime; + return; // ignore any packets that are unreasonable + } + + // Guard against possible corrupted packets... with bad sequence numbers + const int MAX_RESONABLE_SEQUENCE_OFFSET = 2000; + const int MIN_RESONABLE_SEQUENCE_OFFSET = -2000; + int sequenceOffset = (sequence - _incomingLastSequence); + if (sequenceOffset > MAX_RESONABLE_SEQUENCE_OFFSET || sequenceOffset < MIN_RESONABLE_SEQUENCE_OFFSET) { + qDebug() << "ignoring unreasonable packet... sequence:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; + return; // ignore any packets that are unreasonable + } + + // track packets here... + _incomingPacket++; + _incomingBytes += packet.size(); + if (!wasStatsPacket) { + _incomingWastedBytes += (MAX_PACKET_SIZE - packet.size()); + } + const int USECS_PER_MSEC = 1000; float flightTimeMsecs = flightTime / USECS_PER_MSEC; _incomingFlightTimeAverage.updateAverage(flightTimeMsecs); // track out of order and possibly lost packets... - const bool wantExtraDebugging = false; if (sequence == _incomingLastSequence) { if (wantExtraDebugging) { qDebug() << "last packet duplicate got:" << sequence << "_incomingLastSequence:" << _incomingLastSequence; diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index bbb73cae4c..0a9f8df3f7 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -40,10 +40,12 @@ void initialiseUsecTimestampNow() { if (initialised) { qDebug() << "[WARNING] Double initialisation of usecTimestampNow()."; return; - } + } TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec + timestampTimer.start(); initialised = true; + qDebug() << "[INFO] usecTimestampNow() initialized."; } void usecTimestampNowForceClockSkew(int clockSkew) { From 8b4a91004020c8fa2ff0bb38a89ff0f884b2fda2 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 25 Apr 2014 12:19:18 -0700 Subject: [PATCH 74/76] Fix timestamp timer not fired --- assignment-client/src/main.cpp | 2 -- domain-server/src/main.cpp | 2 -- interface/src/main.cpp | 1 - libraries/shared/src/SharedUtil.cpp | 25 ++++++++++--------------- libraries/shared/src/SharedUtil.h | 1 - 5 files changed, 10 insertions(+), 21 deletions(-) diff --git a/assignment-client/src/main.cpp b/assignment-client/src/main.cpp index 7132b5c38a..5e103cf767 100644 --- a/assignment-client/src/main.cpp +++ b/assignment-client/src/main.cpp @@ -17,8 +17,6 @@ #include "AssignmentClientMonitor.h" int main(int argc, char* argv[]) { - initialiseUsecTimestampNow(); - #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/domain-server/src/main.cpp b/domain-server/src/main.cpp index 871c16a215..1d9e837f0a 100644 --- a/domain-server/src/main.cpp +++ b/domain-server/src/main.cpp @@ -23,8 +23,6 @@ #include "DomainServer.h" int main(int argc, char* argv[]) { - initialiseUsecTimestampNow(); - #ifndef WIN32 setvbuf(stdout, NULL, _IOLBF, 0); #endif diff --git a/interface/src/main.cpp b/interface/src/main.cpp index 6f9dc5e3bd..2bb0633f24 100644 --- a/interface/src/main.cpp +++ b/interface/src/main.cpp @@ -16,7 +16,6 @@ #include int main(int argc, const char * argv[]) { - initialiseUsecTimestampNow(); QElapsedTimer startupTime; startupTime.start(); diff --git a/libraries/shared/src/SharedUtil.cpp b/libraries/shared/src/SharedUtil.cpp index bbb73cae4c..c65b7505ee 100644 --- a/libraries/shared/src/SharedUtil.cpp +++ b/libraries/shared/src/SharedUtil.cpp @@ -30,27 +30,22 @@ #include "OctalCode.h" #include "SharedUtil.h" - -static qint64 TIME_REFERENCE = 0; // in usec -static QElapsedTimer timestampTimer; static int usecTimestampNowAdjust = 0; // in usec - -void initialiseUsecTimestampNow() { - static bool initialised = false; - if (initialised) { - qDebug() << "[WARNING] Double initialisation of usecTimestampNow()."; - return; - } - - TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec - initialised = true; -} - void usecTimestampNowForceClockSkew(int clockSkew) { ::usecTimestampNowAdjust = clockSkew; } quint64 usecTimestampNow() { + static bool usecTimestampNowIsInitialized = false; + static qint64 TIME_REFERENCE = 0; // in usec + static QElapsedTimer timestampTimer; + + if (!usecTimestampNowIsInitialized) { + TIME_REFERENCE = QDateTime::currentMSecsSinceEpoch() * 1000; // ms to usec + timestampTimer.start(); + usecTimestampNowIsInitialized = true; + } + // usec nsec to usec usec return TIME_REFERENCE + timestampTimer.nsecsElapsed() / 1000 + ::usecTimestampNowAdjust; } diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 54d599070d..4a3fe2a129 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -60,7 +60,6 @@ static const quint64 USECS_PER_SECOND = USECS_PER_MSEC * MSECS_PER_SECOND; const int BITS_IN_BYTE = 8; -void initialiseUsecTimestampNow(); quint64 usecTimestampNow(); void usecTimestampNowForceClockSkew(int clockSkew); From 8e12c0d8e5ca45bd32f24a3392f6521ab5dbb8c4 Mon Sep 17 00:00:00 2001 From: Stephen Birarda Date: Fri, 25 Apr 2014 13:22:18 -0700 Subject: [PATCH 75/76] pass the owner scope to auth requests --- libraries/networking/src/AccountManager.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/libraries/networking/src/AccountManager.cpp b/libraries/networking/src/AccountManager.cpp index d1e4edf2ea..278923026d 100644 --- a/libraries/networking/src/AccountManager.cpp +++ b/libraries/networking/src/AccountManager.cpp @@ -282,10 +282,13 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas QUrl grantURL = _authURL; grantURL.setPath("/oauth/token"); + const QString ACCOUNT_MANAGER_REQUESTED_SCOPE = "owner"; + QByteArray postData; postData.append("grant_type=password&"); postData.append("username=" + login + "&"); - postData.append("password=" + password); + postData.append("password=" + password + "&"); + postData.append("scope=" + ACCOUNT_MANAGER_REQUESTED_SCOPE); request.setUrl(grantURL); request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded"); From 3143e10bd85029d0adc0136b7251c5fcb8fe09b6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 25 Apr 2014 13:33:59 -0700 Subject: [PATCH 76/76] CR --- libraries/octree/src/Octree.cpp | 13 +++++++++++++ libraries/octree/src/Octree.h | 8 ++++++++ libraries/voxels/src/VoxelTree.cpp | 5 +---- libraries/voxels/src/VoxelTree.h | 7 +++++++ libraries/voxels/src/VoxelTreeCommands.cpp | 2 +- 5 files changed, 30 insertions(+), 5 deletions(-) diff --git a/libraries/octree/src/Octree.cpp b/libraries/octree/src/Octree.cpp index ebfb954bd8..5e812c06c3 100644 --- a/libraries/octree/src/Octree.cpp +++ b/libraries/octree/src/Octree.cpp @@ -542,6 +542,19 @@ OctreeElement* Octree::getOctreeElementAt(float x, float y, float z, float s) co return node; } +OctreeElement* Octree::getOctreeEnclosingElementAt(float x, float y, float z, float s) const { + unsigned char* octalCode = pointToOctalCode(x,y,z,s); + OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); + + delete[] octalCode; // cleanup memory +#ifdef HAS_AUDIT_CHILDREN + if (node) { + node->auditChildren("Octree::getOctreeElementAt()"); + } +#endif // def HAS_AUDIT_CHILDREN + return node; +} + OctreeElement* Octree::getOrCreateChildElementAt(float x, float y, float z, float s) { return getRoot()->getOrCreateChildElementAt(x, y, z, s); diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index 0b9f1657ee..a11e73ab04 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -210,7 +210,15 @@ public: void reaverageOctreeElements(OctreeElement* startNode = NULL); void deleteOctreeElementAt(float x, float y, float z, float s); + + /// Find the voxel at position x,y,z,s + /// \return pointer to the OctreeElement or NULL if none at x,y,z,s. OctreeElement* getOctreeElementAt(float x, float y, float z, float s) const; + + /// Find the voxel at position x,y,z,s + /// \return pointer to the OctreeElement or to the smallest enclosing parent if none at x,y,z,s. + OctreeElement* getOctreeEnclosingElementAt(float x, float y, float z, float s) const; + OctreeElement* getOrCreateChildElementAt(float x, float y, float z, float s); void recurseTreeWithOperation(RecurseOctreeOperation operation, void* extraData = NULL); diff --git a/libraries/voxels/src/VoxelTree.cpp b/libraries/voxels/src/VoxelTree.cpp index aeb877ef78..b1ddf2e5b0 100644 --- a/libraries/voxels/src/VoxelTree.cpp +++ b/libraries/voxels/src/VoxelTree.cpp @@ -46,10 +46,7 @@ VoxelTreeElement* VoxelTree::getVoxelAt(float x, float y, float z, float s) cons } VoxelTreeElement* VoxelTree::getEnclosingVoxelAt(float x, float y, float z, float s) const { - unsigned char* octalCode = pointToOctalCode(x,y,z,s); - OctreeElement* node = nodeForOctalCode(_rootNode, octalCode, NULL); - - return static_cast(node); + return static_cast(getOctreeEnclosingElementAt(x, y, z, s)); } void VoxelTree::createVoxel(float x, float y, float z, float s, diff --git a/libraries/voxels/src/VoxelTree.h b/libraries/voxels/src/VoxelTree.h index 2992815787..eb24c182b2 100644 --- a/libraries/voxels/src/VoxelTree.h +++ b/libraries/voxels/src/VoxelTree.h @@ -29,8 +29,15 @@ public: VoxelTreeElement* getRoot() { return (VoxelTreeElement*)_rootNode; } void deleteVoxelAt(float x, float y, float z, float s); + + /// Find the voxel at position x,y,z,s + /// \return pointer to the VoxelTreeElement or NULL if none at x,y,z,s. VoxelTreeElement* getVoxelAt(float x, float y, float z, float s) const; + + /// Find the voxel at position x,y,z,s + /// \return pointer to the VoxelTreeElement or to the smallest enclosing parent if none at x,y,z,s. VoxelTreeElement* getEnclosingVoxelAt(float x, float y, float z, float s) const; + void createVoxel(float x, float y, float z, float s, unsigned char red, unsigned char green, unsigned char blue, bool destructive = false); diff --git a/libraries/voxels/src/VoxelTreeCommands.cpp b/libraries/voxels/src/VoxelTreeCommands.cpp index a35096b5c7..39e08d3bc2 100644 --- a/libraries/voxels/src/VoxelTreeCommands.cpp +++ b/libraries/voxels/src/VoxelTreeCommands.cpp @@ -22,7 +22,7 @@ struct SendVoxelsOperationArgs { bool sendVoxelsOperation(OctreeElement* element, void* extraData) { VoxelTreeElement* voxel = static_cast(element); - SendVoxelsOperationArgs* args = (SendVoxelsOperationArgs*)extraData; + SendVoxelsOperationArgs* args = static_cast(extraData); if (voxel->isColored()) { const unsigned char* nodeOctalCode = voxel->getOctalCode(); unsigned char* codeColorBuffer = NULL;