This commit is contained in:
Philip Rosedale 2014-09-29 10:52:19 -07:00
commit 4b8003948a
8 changed files with 204 additions and 40 deletions

View file

@ -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);
}

View file

@ -231,7 +231,7 @@ Menu::Menu() :
#ifdef HAVE_QXMPP
_chatAction = addActionToQMenuAndActionHash(toolsMenu,
MenuOption::Chat,
0,
Qt::Key_Backslash,
this,
SLOT(showChat()));

View file

@ -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
@ -1850,11 +1850,152 @@ 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 - center));
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;
}
}
}
// 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, 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) {
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] },

View file

@ -36,9 +36,30 @@ SkeletonModel::~SkeletonModel() {
_ragdoll = NULL;
}
const float MODEL_SCALE = 0.0006f;
void SkeletonModel::setJointStates(QVector<JointState> 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();

View file

@ -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();

View file

@ -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)
{
}
@ -44,9 +45,13 @@ void AudioInjector::setOptions(AudioInjectorOptions& options) {
const uchar MAX_INJECTOR_VOLUME = 0xFF;
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

View file

@ -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

View file

@ -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; }