From 3fe6e3063265e1866161b6cf753d40da3914a692 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 26 Sep 2014 13:43:28 -0700 Subject: [PATCH 1/8] Working on QR decomposition. --- interface/src/MetavoxelSystem.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 1c17819707..885a1b5548 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1850,6 +1850,28 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } normal = glm::normalize(normal); center /= crossingCount; + + // use a sequence of Givens rotations to perform a QR decomposition + // see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf + glm::mat4 r(0.0f); + glm::vec4 bottom; + for (int i = 0; i < crossingCount; i++) { + const EdgeCrossing& crossing = crossings[i]; + bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point)); + + for (int j = 0; j < 4; j++) { + float angle = glm::atan(-bottom[j], r[j][j]); + float sina = glm::sin(angle); + float cosa = glm::cos(angle); + + for (int k = 0; k < 4; k++) { + float tmp = bottom[k]; + bottom[k] = sina * r[k][j] + cosa * tmp; + r[k][j] = cosa * r[k][j] - sina * tmp; + } + } + } + if (totalWeight > 0.0f) { materialWeights *= (EIGHT_BIT_MAXIMUM / totalWeight); } From 6df430660d24b9af929a1c5abbc18cec1b3d5a97 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 26 Sep 2014 15:23:17 -0700 Subject: [PATCH 2/8] Uninitialized member --- libraries/audio/src/AudioInjector.cpp | 6 ++++-- libraries/audio/src/AudioInjector.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 10623651a0..33f92e6599 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -33,7 +33,8 @@ AudioInjector::AudioInjector(QObject* parent) : AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions) : _sound(sound), _options(injectorOptions), - _shouldStop(false) + _shouldStop(false), + _currentSendPosition(0) { } @@ -43,7 +44,8 @@ void AudioInjector::setOptions(AudioInjectorOptions& options) { const uchar MAX_INJECTOR_VOLUME = 0xFF; -void AudioInjector::injectAudio() { +void AudioInjector::injectAudio(int startingPosition) { + _currentSendPosition = startingPosition; QByteArray soundByteArray = _sound->getByteArray(); diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index af9b5e55d1..bf93221e91 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -29,7 +29,7 @@ public: int getCurrentSendPosition() const { return _currentSendPosition; } public slots: - void injectAudio(); + void injectAudio(int startingPosition = 0); void stop() { _shouldStop = true; } void setOptions(AudioInjectorOptions& options); void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; } From dfe70ed2e359bf86be7fc7483a008e2ba07e24b5 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 26 Sep 2014 19:23:36 -0700 Subject: [PATCH 3/8] Initialize InjectedAudioStream with correct stereo value --- .../src/audio/AudioMixerClientData.cpp | 5 ++++- libraries/audio/src/InjectedAudioStream.cpp | 15 ++++++++++----- libraries/audio/src/InjectedAudioStream.h | 2 +- 3 files changed, 15 insertions(+), 7 deletions(-) diff --git a/assignment-client/src/audio/AudioMixerClientData.cpp b/assignment-client/src/audio/AudioMixerClientData.cpp index 6c326b3d28..2f60640da3 100644 --- a/assignment-client/src/audio/AudioMixerClientData.cpp +++ b/assignment-client/src/audio/AudioMixerClientData.cpp @@ -89,10 +89,13 @@ int AudioMixerClientData::parseData(const QByteArray& packet) { // grab the stream identifier for this injected audio int bytesBeforeStreamIdentifier = numBytesForPacketHeader(packet) + sizeof(quint16); QUuid streamIdentifier = QUuid::fromRfc4122(packet.mid(bytesBeforeStreamIdentifier, NUM_BYTES_RFC4122_UUID)); + int bytesBeforeStereoIdentifier = bytesBeforeStreamIdentifier + NUM_BYTES_RFC4122_UUID; + bool isStereo; + QDataStream(packet.mid(bytesBeforeStereoIdentifier)) >> isStereo; if (!_audioStreams.contains(streamIdentifier)) { // we don't have this injected stream yet, so add it - _audioStreams.insert(streamIdentifier, matchingStream = new InjectedAudioStream(streamIdentifier, AudioMixer::getStreamSettings())); + _audioStreams.insert(streamIdentifier, matchingStream = new InjectedAudioStream(streamIdentifier, isStereo, AudioMixer::getStreamSettings())); } else { matchingStream = _audioStreams.value(streamIdentifier); } diff --git a/libraries/audio/src/InjectedAudioStream.cpp b/libraries/audio/src/InjectedAudioStream.cpp index 0cc13eae05..873b32cc40 100644 --- a/libraries/audio/src/InjectedAudioStream.cpp +++ b/libraries/audio/src/InjectedAudioStream.cpp @@ -19,8 +19,8 @@ #include "InjectedAudioStream.h" -InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, const InboundAudioStream::Settings& settings) : - PositionalAudioStream(PositionalAudioStream::Injector, false, settings), +InjectedAudioStream::InjectedAudioStream(const QUuid& streamIdentifier, const bool isStereo, const InboundAudioStream::Settings& settings) : + PositionalAudioStream(PositionalAudioStream::Injector, isStereo, settings), _streamIdentifier(streamIdentifier), _radius(0.0f), _attenuationRatio(0) @@ -39,9 +39,14 @@ int InjectedAudioStream::parseStreamProperties(PacketType type, // skip the stream identifier packetStream.skipRawData(NUM_BYTES_RFC4122_UUID); - packetStream >> _isStereo; - if (isStereo()) { - _ringBuffer.resizeForFrameSize(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO); + // read the channel flag + bool isStereo; + packetStream >> isStereo; + + // if isStereo value has changed, restart the ring buffer with new frame size + if (isStereo != _isStereo) { + _ringBuffer.resizeForFrameSize(isStereo ? NETWORK_BUFFER_LENGTH_SAMPLES_STEREO : NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL); + _isStereo = isStereo; } // pull the loopback flag and set our boolean diff --git a/libraries/audio/src/InjectedAudioStream.h b/libraries/audio/src/InjectedAudioStream.h index f3840b1029..60c36dfb12 100644 --- a/libraries/audio/src/InjectedAudioStream.h +++ b/libraries/audio/src/InjectedAudioStream.h @@ -18,7 +18,7 @@ class InjectedAudioStream : public PositionalAudioStream { public: - InjectedAudioStream(const QUuid& streamIdentifier, const InboundAudioStream::Settings& settings); + InjectedAudioStream(const QUuid& streamIdentifier, const bool isStereo, const InboundAudioStream::Settings& settings); float getRadius() const { return _radius; } float getAttenuationRatio() const { return _attenuationRatio; } From 8ebb2a7fb4ca96ab30f99df645fd4486131e0c0d Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 26 Sep 2014 19:32:41 -0700 Subject: [PATCH 4/8] Ridiculously complicated minimization code. --- interface/src/MetavoxelSystem.cpp | 149 +++++++++++++++++++++++++++--- 1 file changed, 134 insertions(+), 15 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 885a1b5548..4961d4dbd4 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1657,7 +1657,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[0]; crossing.material = materialBase[0]; } - crossing.point = glm::vec3(qAlpha(hermite), 0.0f, 0.0f); + crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 0.0f); } if (middleY) { if (alpha1 != alpha3) { @@ -1671,7 +1671,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[1]; crossing.material = materialBase[1]; } - crossing.point = glm::vec3(EIGHT_BIT_MAXIMUM, qAlpha(hermite), 0.0f); + crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f); } if (alpha2 != alpha3) { QRgb hermite = hermiteBase[hermiteStride]; @@ -1684,7 +1684,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[size]; crossing.material = materialBase[size]; } - crossing.point = glm::vec3(qAlpha(hermite), EIGHT_BIT_MAXIMUM, 0.0f); + crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 0.0f); } if (middleZ) { if (alpha3 != alpha7) { @@ -1698,7 +1698,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[offset3]; crossing.material = materialBase[offset3]; } - crossing.point = glm::vec3(EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM, qAlpha(hermite)); + crossing.point = glm::vec3(1.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); } if (alpha5 != alpha7) { QRgb hermite = hermiteBase[hermiteArea + VoxelHermiteData::EDGE_COUNT + 1]; @@ -1711,7 +1711,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[offset5]; crossing.material = materialBase[offset5]; } - crossing.point = glm::vec3(EIGHT_BIT_MAXIMUM, qAlpha(hermite), EIGHT_BIT_MAXIMUM); + crossing.point = glm::vec3(1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f); } if (alpha6 != alpha7) { QRgb hermite = hermiteBase[hermiteArea + hermiteStride]; @@ -1724,7 +1724,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[offset6]; crossing.material = materialBase[offset6]; } - crossing.point = glm::vec3(qAlpha(hermite), EIGHT_BIT_MAXIMUM, EIGHT_BIT_MAXIMUM); + crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f, 1.0f); } } } @@ -1740,7 +1740,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[1]; crossing.material = materialBase[1]; } - crossing.point = glm::vec3(EIGHT_BIT_MAXIMUM, 0.0f, qAlpha(hermite)); + crossing.point = glm::vec3(1.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); } if (alpha4 != alpha5) { QRgb hermite = hermiteBase[hermiteArea]; @@ -1753,7 +1753,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[area]; crossing.material = materialBase[area]; } - crossing.point = glm::vec3(qAlpha(hermite), 0.0f, EIGHT_BIT_MAXIMUM); + crossing.point = glm::vec3(qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f, 1.0f); } } } @@ -1769,7 +1769,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[0]; crossing.material = materialBase[0]; } - crossing.point = glm::vec3(0.0f, qAlpha(hermite), 0.0f); + crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 0.0f); } if (middleZ) { if (alpha2 != alpha6) { @@ -1783,7 +1783,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[size]; crossing.material = materialBase[size]; } - crossing.point = glm::vec3(0.0f, EIGHT_BIT_MAXIMUM, qAlpha(hermite)); + crossing.point = glm::vec3(0.0f, 1.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); } if (alpha4 != alpha6) { QRgb hermite = hermiteBase[hermiteArea + 1]; @@ -1796,7 +1796,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[area]; crossing.material = materialBase[area]; } - crossing.point = glm::vec3(0.0f, qAlpha(hermite), EIGHT_BIT_MAXIMUM); + crossing.point = glm::vec3(0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL, 1.0f); } } } @@ -1811,7 +1811,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { crossing.color = colorX[0]; crossing.material = materialBase[0]; } - crossing.point = glm::vec3(0.0f, 0.0f, qAlpha(hermite)); + crossing.point = glm::vec3(0.0f, 0.0f, qAlpha(hermite) * EIGHT_BIT_MAXIMUM_RECIPROCAL); } // at present, we simply average the properties of each crossing as opposed to finding the vertex that // minimizes the quadratic error function as described in the reference paper @@ -1857,7 +1857,7 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { glm::vec4 bottom; for (int i = 0; i < crossingCount; i++) { const EdgeCrossing& crossing = crossings[i]; - bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point)); + bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center)); for (int j = 0; j < 4; j++) { float angle = glm::atan(-bottom[j], r[j][j]); @@ -1872,11 +1872,130 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } } + // extract the submatrices, form ata + glm::mat3 a(r); + glm::vec3 b(r[3]); + glm::mat3 atrans = glm::transpose(a); + glm::mat3 ata = atrans * a; + + // compute the SVD of ata; first, find the eigenvalues + // (see http://en.wikipedia.org/wiki/Eigenvalue_algorithm#3.C3.973_matrices) + glm::vec3 eigenvalues; + float p1 = ata[0][1] * ata[0][1] + ata[0][2] * ata[0][2] + ata[1][2] * ata[1][2]; + if (p1 < EPSILON) { + eigenvalues = glm::vec3(ata[0][0], ata[1][1], ata[2][2]); + if (eigenvalues[2] < eigenvalues[1]) { + qSwap(eigenvalues[2], eigenvalues[1]); + } + if (eigenvalues[1] < eigenvalues[0]) { + qSwap(eigenvalues[1], eigenvalues[0]); + } + if (eigenvalues[2] < eigenvalues[1]) { + qSwap(eigenvalues[2], eigenvalues[1]); + } + } else { + float q = (ata[0][0] + ata[1][1] + ata[2][2]) / 3.0f; + float d1 = ata[0][0] - q, d2 = ata[1][1] - q, d3 = ata[2][2] - q; + float p2 = d1 * d1 + d2 * d2 + d3 * d3 + 2.0f * p1; + float p = glm::sqrt(p2 / 6.0f); + glm::mat3 b = (ata - glm::mat3(q)) / p; + float r = glm::determinant(b) / 2.0f; + float phi; + if (r <= -1.0f) { + phi = PI / 3.0f; + } else if (r >= 1.0f) { + phi = 0.0f; + } else { + phi = glm::acos(r) / 3.0f; + } + eigenvalues[2] = q + 2.0f * p * glm::cos(phi); + eigenvalues[0] = q + 2.0f * p * glm::cos(phi + (2.0f * PI / 3.0f)); + eigenvalues[1] = 3.0f * q - eigenvalues[0] - eigenvalues[2]; + } + + // form the singular matrix from the eigenvalues + glm::mat3 d; + const float MIN_SINGULAR_THRESHOLD = 0.1f; + d[0][0] = (eigenvalues[0] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[0]; + d[1][1] = (eigenvalues[1] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[1]; + d[2][2] = (eigenvalues[2] < MIN_SINGULAR_THRESHOLD) ? 0.0f : 1.0f / eigenvalues[2]; + + glm::mat3 m[] = { ata - glm::mat3(eigenvalues[0]), ata - glm::mat3(eigenvalues[1]), + ata - glm::mat3(eigenvalues[2]) }; + + // form the orthogonal matrix from the eigenvectors + // see http://www.geometrictools.com/Documentation/EigenSymmetric3x3.pdf + bool same01 = glm::abs(eigenvalues[0] - eigenvalues[1]) < EPSILON; + bool same12 = glm::abs(eigenvalues[1] - eigenvalues[2]) < EPSILON; + glm::mat3 u; + if (!(same01 && same12)) { + if (same01 || same12) { + int i = same01 ? 2 : 0; + for (int j = 0; j < 3; j++) { + glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); + int j2 = (j + 1) % 3; + glm::vec3 second = glm::vec3(m[i][0][j2], m[i][1][j2], m[i][2][j2]); + glm::vec3 cross = glm::cross(first, second); + float length = glm::length(cross); + if (length > EPSILON) { + u[0][i] = cross[0] / length; + u[1][i] = cross[1] / length; + u[2][i] = cross[2] / length; + break; + } + } + i = (i + 1) % 3; + for (int j = 0; j < 3; j++) { + glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); + float length = glm::length(first); + if (length > EPSILON) { + glm::vec3 second = glm::cross(first, glm::vec3(1.0f, 0.0f, 0.0f)); + length = glm::length(second); + if (length < EPSILON) { + second = glm::cross(first, glm::vec3(0.0f, 1.0f, 0.0f)); + length = glm::length(second); + } + u[0][i] = second[0] / length; + u[1][i] = second[1] / length; + u[2][i] = second[2] / length; + second = glm::normalize(glm::cross(second, first)); + i = (i + 1) % 3; + u[0][i] = second[0]; + u[1][i] = second[1]; + u[2][i] = second[2]; + break; + } + } + } else { + for (int i = 0; i < 3; i++) { + for (int j = 0; j < 3; j++) { + glm::vec3 first = glm::vec3(m[i][0][j], m[i][1][j], m[i][2][j]); + int j2 = (j + 1) % 3; + glm::vec3 second = glm::vec3(m[i][0][j2], m[i][1][j2], m[i][2][j2]); + glm::vec3 cross = glm::cross(first, second); + float length = glm::length(cross); + if (length > EPSILON) { + u[0][i] = cross[0] / length; + u[1][i] = cross[1] / length; + u[2][i] = cross[2] / length; + break; + } + } + } + } + } + + // compute the pseudo-inverse, ataplus + glm::mat3 ataplus = glm::transpose(u) * d * u; + + glm::vec3 solution = (ataplus * atrans * b) + center; + + center = glm::clamp(solution, 0.0f, 1.0f); + if (totalWeight > 0.0f) { materialWeights *= (EIGHT_BIT_MAXIMUM / totalWeight); } - VoxelPoint point = { info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) + - center * EIGHT_BIT_MAXIMUM_RECIPROCAL) * scale, + VoxelPoint point = { info.minimum + (glm::vec3(clampedX, clampedY, clampedZ) + center) * scale, { (quint8)(red / crossingCount), (quint8)(green / crossingCount), (quint8)(blue / crossingCount) }, { (char)(normal.x * 127.0f), (char)(normal.y * 127.0f), (char)(normal.z * 127.0f) }, { materials[0], materials[1], materials[2], materials[3] }, From 5a8b9082b25e187373588ef08a140577492564e4 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 26 Sep 2014 19:47:26 -0700 Subject: [PATCH 5/8] Check _currentSendPosition instead of overriding --- libraries/audio/src/AudioInjector.cpp | 9 ++++++--- libraries/audio/src/AudioInjector.h | 2 +- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/libraries/audio/src/AudioInjector.cpp b/libraries/audio/src/AudioInjector.cpp index 33f92e6599..d5e1c59d7a 100644 --- a/libraries/audio/src/AudioInjector.cpp +++ b/libraries/audio/src/AudioInjector.cpp @@ -44,11 +44,14 @@ void AudioInjector::setOptions(AudioInjectorOptions& options) { const uchar MAX_INJECTOR_VOLUME = 0xFF; -void AudioInjector::injectAudio(int startingPosition) { - _currentSendPosition = startingPosition; - +void AudioInjector::injectAudio() { QByteArray soundByteArray = _sound->getByteArray(); + if (_currentSendPosition < 0 || + _currentSendPosition >= soundByteArray.size()) { + _currentSendPosition = 0; + } + // make sure we actually have samples downloaded to inject if (soundByteArray.size()) { // give our sample byte array to the local audio interface, if we have it, so it can be handled locally diff --git a/libraries/audio/src/AudioInjector.h b/libraries/audio/src/AudioInjector.h index bf93221e91..af9b5e55d1 100644 --- a/libraries/audio/src/AudioInjector.h +++ b/libraries/audio/src/AudioInjector.h @@ -29,7 +29,7 @@ public: int getCurrentSendPosition() const { return _currentSendPosition; } public slots: - void injectAudio(int startingPosition = 0); + void injectAudio(); void stop() { _shouldStop = true; } void setOptions(AudioInjectorOptions& options); void setCurrentSendPosition(int currentSendPosition) { _currentSendPosition = currentSendPosition; } From 7d78584aeee6d2ae3176f438fcc3d8b3268439a6 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 26 Sep 2014 20:11:14 -0700 Subject: [PATCH 6/8] Fix chat shortcut --- interface/src/Menu.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index cd5677e9e5..8f7b2be43b 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -231,7 +231,7 @@ Menu::Menu() : #ifdef HAVE_QXMPP _chatAction = addActionToQMenuAndActionHash(toolsMenu, MenuOption::Chat, - 0, + Qt::Key_Backslash, this, SLOT(showChat())); From 681bb60d0324b073beeb7b2046af3e8b91d04f25 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Fri, 26 Sep 2014 20:24:24 -0700 Subject: [PATCH 7/8] Could extra comments. --- interface/src/MetavoxelSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 4961d4dbd4..b993d5243e 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -1985,11 +1985,11 @@ int VoxelAugmentVisitor::visit(MetavoxelInfo& info) { } } - // compute the pseudo-inverse, ataplus + // compute the pseudo-inverse, ataplus, and use to find the minimizing solution glm::mat3 ataplus = glm::transpose(u) * d * u; - glm::vec3 solution = (ataplus * atrans * b) + center; + // make sure it doesn't fall beyond the cell boundaries center = glm::clamp(solution, 0.0f, 1.0f); if (totalWeight > 0.0f) { From dbf6daf80c5475b1bcd87b223192a30b84cdac55 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Sat, 27 Sep 2014 11:25:37 -0700 Subject: [PATCH 8/8] Fix default eye model calculation to be reliable --- interface/src/avatar/SkeletonModel.cpp | 40 ++++++++++++++++---------- interface/src/avatar/SkeletonModel.h | 2 +- 2 files changed, 26 insertions(+), 16 deletions(-) diff --git a/interface/src/avatar/SkeletonModel.cpp b/interface/src/avatar/SkeletonModel.cpp index 1af5cfc893..a1fccf1a10 100644 --- a/interface/src/avatar/SkeletonModel.cpp +++ b/interface/src/avatar/SkeletonModel.cpp @@ -36,9 +36,30 @@ SkeletonModel::~SkeletonModel() { _ragdoll = NULL; } +const float MODEL_SCALE = 0.0006f; + void SkeletonModel::setJointStates(QVector states) { Model::setJointStates(states); + // Determine the default eye position for avatar scale = 1.0 + int headJointIndex = _geometry->getFBXGeometry().headJointIndex; + if (0 <= headJointIndex && headJointIndex < _jointStates.size()) { + + glm::vec3 leftEyePosition, rightEyePosition; + getEyeModelPositions(leftEyePosition, rightEyePosition); + glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.f; + + int rootJointIndex = _geometry->getFBXGeometry().rootJointIndex; + glm::vec3 rootModelPosition; + getJointPosition(rootJointIndex, rootModelPosition); + + _defaultEyeModelPosition = midEyePosition - rootModelPosition; + _defaultEyeModelPosition.z = -_defaultEyeModelPosition.z; + + // Skeleton may have already been scaled so unscale it + _defaultEyeModelPosition = MODEL_SCALE * _defaultEyeModelPosition / _scale; + } + // the SkeletonModel override of updateJointState() will clear the translation part // of its root joint and we need that done before we try to build shapes hence we // recompute all joint transforms at this time. @@ -59,7 +80,6 @@ void SkeletonModel::simulate(float deltaTime, bool fullUpdate) { setTranslation(_owningAvatar->getPosition()); static const glm::quat refOrientation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)); setRotation(_owningAvatar->getOrientation() * refOrientation); - const float MODEL_SCALE = 0.0006f; setScale(glm::vec3(1.0f, 1.0f, 1.0f) * _owningAvatar->getScale() * MODEL_SCALE); setBlendshapeCoefficients(_owningAvatar->getHead()->getBlendshapeCoefficients()); @@ -507,6 +527,10 @@ bool SkeletonModel::getEyePositions(glm::vec3& firstEyePosition, glm::vec3& seco return false; } +glm::vec3 SkeletonModel::getDefaultEyeModelPosition() const { + return _owningAvatar->getScale() * _defaultEyeModelPosition; +} + void SkeletonModel::renderRagdoll() { if (!_ragdoll) { return; @@ -666,20 +690,6 @@ void SkeletonModel::buildShapes() { // This method moves the shapes to their default positions in Model frame. computeBoundingShape(geometry); - int headJointIndex = _geometry->getFBXGeometry().headJointIndex; - if (0 <= headJointIndex && headJointIndex < _jointStates.size()) { - glm::vec3 leftEyePosition, rightEyePosition; - getEyeModelPositions(leftEyePosition, rightEyePosition); - glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.f; - - int rootJointIndex = _geometry->getFBXGeometry().rootJointIndex; - glm::vec3 rootModelPosition; - getJointPosition(rootJointIndex, rootModelPosition); - - _defaultEyeModelPosition = midEyePosition - rootModelPosition; - _defaultEyeModelPosition.z = -_defaultEyeModelPosition.z; - } - // While the shapes are in their default position we disable collisions between // joints that are currently colliding. disableCurrentSelfCollisions(); diff --git a/interface/src/avatar/SkeletonModel.h b/interface/src/avatar/SkeletonModel.h index 35122d5e18..81e3fcb3b6 100644 --- a/interface/src/avatar/SkeletonModel.h +++ b/interface/src/avatar/SkeletonModel.h @@ -99,7 +99,7 @@ public: /// Gets the default position of the mid eye point in model frame coordinates. /// \return whether or not the head was found. - glm::vec3 getDefaultEyeModelPosition() const { return _defaultEyeModelPosition; } + glm::vec3 getDefaultEyeModelPosition() const; virtual void updateVisibleJointStates();