Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2014-03-28 11:19:58 -07:00
commit cc5ea2a465
33 changed files with 517 additions and 402 deletions

View file

@ -18,6 +18,7 @@
#include <SharedUtil.h>
#include "AssignmentFactory.h"
#include "AssignmentThread.h"
#include "AssignmentClient.h"
@ -28,7 +29,7 @@ int hifiSockAddrMeta = qRegisterMetaType<HifiSockAddr>("HifiSockAddr");
AssignmentClient::AssignmentClient(int &argc, char **argv) :
QCoreApplication(argc, argv),
_currentAssignment(NULL)
_currentAssignment()
{
setOrganizationName("High Fidelity");
setOrganizationDomain("highfidelity.io");
@ -124,7 +125,7 @@ void AssignmentClient::readPendingDatagrams() {
if (nodeList->packetVersionAndHashMatch(receivedPacket)) {
if (packetTypeForPacket(receivedPacket) == PacketTypeCreateAssignment) {
// construct the deployed assignment from the packet data
_currentAssignment = AssignmentFactory::unpackAssignment(receivedPacket);
_currentAssignment = SharedAssignmentPointer(AssignmentFactory::unpackAssignment(receivedPacket));
if (_currentAssignment) {
qDebug() << "Received an assignment -" << *_currentAssignment;
@ -137,14 +138,13 @@ void AssignmentClient::readPendingDatagrams() {
qDebug() << "Destination IP for assignment is" << nodeList->getDomainInfo().getIP().toString();
// start the deployed assignment
QThread* workerThread = new QThread(this);
AssignmentThread* workerThread = new AssignmentThread(_currentAssignment, this);
connect(workerThread, SIGNAL(started()), _currentAssignment, SLOT(run()));
connect(_currentAssignment, SIGNAL(finished()), this, SLOT(assignmentCompleted()));
connect(_currentAssignment, SIGNAL(finished()), workerThread, SLOT(quit()));
connect(_currentAssignment, SIGNAL(finished()), _currentAssignment, SLOT(deleteLater()));
connect(workerThread, SIGNAL(finished()), workerThread, SLOT(deleteLater()));
connect(workerThread, &QThread::started, _currentAssignment.data(), &ThreadedAssignment::run);
connect(_currentAssignment.data(), &ThreadedAssignment::finished, workerThread, &QThread::quit);
connect(_currentAssignment.data(), &ThreadedAssignment::finished,
this, &AssignmentClient::assignmentCompleted);
connect(workerThread, &QThread::finished, workerThread, &QThread::deleteLater);
_currentAssignment->moveToThread(workerThread);
@ -153,7 +153,7 @@ void AssignmentClient::readPendingDatagrams() {
// let the assignment handle the incoming datagrams for its duration
disconnect(&nodeList->getNodeSocket(), 0, this, 0);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment,
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _currentAssignment.data(),
&ThreadedAssignment::readPendingDatagrams);
// Starts an event loop, and emits workerThread->started()
@ -202,10 +202,12 @@ void AssignmentClient::assignmentCompleted() {
NodeList* nodeList = NodeList::getInstance();
// have us handle incoming NodeList datagrams again
disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment, 0);
disconnect(&nodeList->getNodeSocket(), 0, _currentAssignment.data(), 0);
connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, this, &AssignmentClient::readPendingDatagrams);
_currentAssignment = NULL;
// clear our current assignment shared pointer now that we're done with it
// if the assignment thread is still around it has its own shared pointer to the assignment
_currentAssignment.clear();
// reset our NodeList by switching back to unassigned and clearing the list
nodeList->setOwnerType(NodeType::Unassigned);

View file

@ -24,7 +24,7 @@ private slots:
void handleAuthenticationRequest();
private:
Assignment _requestAssignment;
ThreadedAssignment* _currentAssignment;
SharedAssignmentPointer _currentAssignment;
};
#endif /* defined(__hifi__AssignmentClient__) */

View file

@ -0,0 +1,16 @@
//
// AssignmentThread.cpp
// hifi
//
// Created by Stephen Birarda on 2014-03-28.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#include "AssignmentThread.h"
AssignmentThread::AssignmentThread(const SharedAssignmentPointer& assignment, QObject* parent) :
QThread(parent),
_assignment(assignment)
{
}

View file

@ -0,0 +1,23 @@
//
// AssignmentThread.h
// hifi
//
// Created by Stephen Birarda on 2014-03-28.
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#ifndef __hifi__AssignmentThread__
#define __hifi__AssignmentThread__
#include <QtCore/QThread>
#include <ThreadedAssignment.h>
class AssignmentThread : public QThread {
public:
AssignmentThread(const SharedAssignmentPointer& assignment, QObject* parent);
private:
SharedAssignmentPointer _assignment;
};
#endif /* defined(__hifi__AssignmentThread__) */

View file

@ -14,12 +14,12 @@
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3610"/>
<location filename="src/Application.cpp" line="3617"/>
<source>Open Script</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="src/Application.cpp" line="3611"/>
<location filename="src/Application.cpp" line="3618"/>
<source>JavaScript Files (*.js)</source>
<translation type="unfinished"></translation>
</message>
@ -27,25 +27,25 @@
<context>
<name>ChatWindow</name>
<message>
<location filename="ui/chatWindow.ui" line="20"/>
<location filename="../build/interface/ui_chatWindow.h" line="143"/>
<location filename="ui/chatWindow.ui" line="29"/>
<location filename="../build/interface/ui_chatWindow.h" line="153"/>
<source>Chat</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="50"/>
<location filename="../build/interface/ui_chatWindow.h" line="144"/>
<location filename="ui/chatWindow.ui" line="57"/>
<location filename="../build/interface/ui_chatWindow.h" line="154"/>
<source>Connecting to XMPP...</source>
<translation type="unfinished"></translation>
</message>
<message>
<location filename="ui/chatWindow.ui" line="71"/>
<location filename="../build/interface/ui_chatWindow.h" line="145"/>
<location filename="ui/chatWindow.ui" line="78"/>
<location filename="../build/interface/ui_chatWindow.h" line="155"/>
<source> online now:</source>
<translation type="unfinished"></translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<location filename="src/ui/ChatWindow.cpp" line="135"/>
<source>day</source>
<translation>
<numerusform>%n day</numerusform>
@ -53,7 +53,7 @@
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<location filename="src/ui/ChatWindow.cpp" line="135"/>
<source>hour</source>
<translation>
<numerusform>%n hour</numerusform>
@ -61,7 +61,7 @@
</translation>
</message>
<message numerus="yes">
<location filename="src/ui/ChatWindow.cpp" line="128"/>
<location filename="src/ui/ChatWindow.cpp" line="135"/>
<source>minute</source>
<translation>
<numerusform>%n minute</numerusform>
@ -76,7 +76,7 @@
</translation>
</message>
<message>
<location filename="src/ui/ChatWindow.cpp" line="183"/>
<location filename="src/ui/ChatWindow.cpp" line="191"/>
<source>%1 online now:</source>
<translation type="unfinished"></translation>
</message>

View file

@ -2189,19 +2189,26 @@ void Application::updateShadowMap() {
(_viewFrustum.getFarClip() - _viewFrustum.getNearClip());
loadViewFrustum(_myCamera, _viewFrustum);
glm::vec3 points[] = {
inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale)),
inverseRotation * (glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale)) };
glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX);
glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), nearScale),
glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), nearScale),
glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), nearScale),
glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), nearScale),
glm::mix(_viewFrustum.getNearTopLeft(), _viewFrustum.getFarTopLeft(), farScale),
glm::mix(_viewFrustum.getNearTopRight(), _viewFrustum.getFarTopRight(), farScale),
glm::mix(_viewFrustum.getNearBottomLeft(), _viewFrustum.getFarBottomLeft(), farScale),
glm::mix(_viewFrustum.getNearBottomRight(), _viewFrustum.getFarBottomRight(), farScale) };
glm::vec3 center;
for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
minima = glm::min(minima, points[i]);
maxima = glm::max(maxima, points[i]);
center += points[i];
}
center /= (float)(sizeof(points) / sizeof(points[0]));
float radius = 0.0f;
for (size_t i = 0; i < sizeof(points) / sizeof(points[0]); i++) {
radius = qMax(radius, glm::distance(points[i], center));
}
center = inverseRotation * center;
glm::vec3 minima(center.x - radius, center.y - radius, center.z - radius);
glm::vec3 maxima(center.x + radius, center.y + radius, center.z + radius);
// stretch out our extents in z so that we get all of the avatars
minima.z -= _viewFrustum.getFarClip() * 0.5f;

View file

@ -522,7 +522,7 @@ void Audio::handleAudioInput() {
if (audioMixer && audioMixer->getActiveSocket()) {
MyAvatar* interfaceAvatar = Application::getInstance()->getAvatar();
glm::vec3 headPosition = interfaceAvatar->getHead()->getPosition();
glm::quat headOrientation = interfaceAvatar->getHead()->getTweakedOrientation();
glm::quat headOrientation = interfaceAvatar->getHead()->getFinalOrientation();
// we need the amount of bytes in the buffer + 1 for type
// + 12 for 3 floats for position + float for bearing + 1 attenuation byte

View file

@ -924,14 +924,17 @@ void Menu::goTo() {
int dialogReturn = gotoDialog.exec();
if (dialogReturn == QDialog::Accepted && !gotoDialog.textValue().isEmpty()) {
LocationManager* manager = &LocationManager::getInstance();
manager->goTo(gotoDialog.textValue());
connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision);
goToUser(gotoDialog.textValue());
}
sendFakeEnterEvent();
}
void Menu::goToUser(const QString& user) {
LocationManager* manager = &LocationManager::getInstance();
manager->goTo(user);
connect(manager, &LocationManager::multipleDestinationsFound, this, &Menu::multipleDestinationsDecision);
}
void Menu::multipleDestinationsDecision(const QJsonObject& userData, const QJsonObject& placeData) {
QMessageBox msgBox;
msgBox.setText("Both user and location exists with same name");
@ -1099,13 +1102,23 @@ void Menu::showMetavoxelEditor() {
}
void Menu::showChat() {
QMainWindow* mainWindow = Application::getInstance()->getWindow();
if (!_chatWindow) {
Application::getInstance()->getWindow()->addDockWidget(Qt::RightDockWidgetArea, _chatWindow = new ChatWindow());
} else {
if (!_chatWindow->toggleViewAction()->isChecked()) {
_chatWindow->toggleViewAction()->trigger();
}
mainWindow->addDockWidget(Qt::NoDockWidgetArea, _chatWindow = new ChatWindow());
}
if (!_chatWindow->toggleViewAction()->isChecked()) {
int width = _chatWindow->width();
int y = qMax((mainWindow->height() - _chatWindow->height()) / 2, 0);
_chatWindow->move(mainWindow->width(), y);
_chatWindow->resize(0, _chatWindow->height());
_chatWindow->toggleViewAction()->trigger();
QPropertyAnimation* slideAnimation = new QPropertyAnimation(_chatWindow, "geometry", _chatWindow);
slideAnimation->setStartValue(_chatWindow->geometry());
slideAnimation->setEndValue(QRect(mainWindow->width() - width, _chatWindow->y(),
width, _chatWindow->height()));
slideAnimation->setDuration(250);
slideAnimation->start(QAbstractAnimation::DeleteWhenStopped);
}
}

View file

@ -122,6 +122,7 @@ public slots:
void importSettings();
void exportSettings();
void goTo();
void goToUser(const QString& user);
void pasteToVoxel();
void toggleLoginMenuItem();

View file

@ -246,7 +246,8 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode) {
const float DISPLAYNAME_DISTANCE = 10.0f;
setShowDisplayName(renderMode == NORMAL_RENDER_MODE && distanceToTarget < DISPLAYNAME_DISTANCE);
if (renderMode != NORMAL_RENDER_MODE) {
if (renderMode != NORMAL_RENDER_MODE || (isMyAvatar() &&
Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_FIRST_PERSON)) {
return;
}
renderDisplayName();
@ -312,9 +313,7 @@ glm::quat Avatar::computeRotationFromBodyToWorldUp(float proportion) const {
void Avatar::renderBody(RenderMode renderMode) {
if (_shouldRenderBillboard || !(_skeletonModel.isRenderable() && getHead()->getFaceModel().isRenderable())) {
// render the billboard until both models are loaded
if (renderMode != SHADOW_RENDER_MODE) {
renderBillboard();
}
renderBillboard();
return;
}
_skeletonModel.render(1.0f, renderMode == SHADOW_RENDER_MODE);
@ -762,25 +761,6 @@ bool Avatar::collisionWouldMoveAvatar(CollisionInfo& collision) const {
return false;
}
void Avatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) {
// compute lean angles
glm::vec3 leverAxis = contactPoint - getPosition();
float leverLength = glm::length(leverAxis);
if (leverLength > EPSILON) {
glm::quat bodyRotation = getOrientation();
glm::vec3 xAxis = bodyRotation * glm::vec3(1.f, 0.f, 0.f);
glm::vec3 zAxis = bodyRotation * glm::vec3(0.f, 0.f, 1.f);
leverAxis = leverAxis / leverLength;
glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis;
// we use the small-angle approximation for sine below to compute the length of
// the opposite side of a narrow right triangle
float sideways = - glm::dot(effectivePenetration, xAxis) / leverLength;
float forward = glm::dot(effectivePenetration, zAxis) / leverLength;
getHead()->addLean(sideways, forward);
}
}
float Avatar::getBoundingRadius() const {
// TODO: also use head model when computing the avatar's bounding radius
return _skeletonModel.getBoundingRadius();

View file

@ -145,7 +145,7 @@ public:
/// \return true if we expect the avatar would move as a result of the collision
bool collisionWouldMoveAvatar(CollisionInfo& collision) const;
void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration);
virtual void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) { }
/// \return bounding radius of avatar
virtual float getBoundingRadius() const;

View file

@ -50,9 +50,9 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
glm::mat3 axes = glm::mat3_cast(_rotation);
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
joint.preTransform * glm::mat4_cast(joint.preRotation)));
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getTweakedRoll(), glm::normalize(inverse * axes[2]))
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getTweakedYaw(), glm::normalize(inverse * axes[1]))
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getTweakedPitch(), glm::normalize(inverse * axes[0]))
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
* glm::angleAxis(RADIANS_PER_DEGREE * _owningHead->getFinalYaw(), glm::normalize(inverse * axes[1]))
* glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalPitch(), glm::normalize(inverse * axes[0]))
* joint.rotation;
}
@ -60,7 +60,7 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
// likewise with the eye joints
glm::mat4 inverse = glm::inverse(parentState.transform * glm::translate(state.translation) *
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation));
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getTweakedOrientation() * IDENTITY_FRONT, 0.0f));
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getFinalOrientation() * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
_owningHead->getSaccade() - _translation, 1.0f));
glm::quat between = rotationBetween(front, lookAt);

View file

@ -156,7 +156,8 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
//palm.addToPenetration(averagePenetration);
} else {
// someone else's hand against MyAvatar
averageContactPoint /= float(handCollisions.size());
// TODO: submit collision info to MyAvatar which should lean accordingly
averageContactPoint /= (float)handCollisions.size();
avatar->applyCollision(averageContactPoint, totalPenetration);
}
}

View file

@ -36,9 +36,11 @@ Head::Head(Avatar* owningAvatar) :
_leftEyeBlinkVelocity(0.0f),
_rightEyeBlinkVelocity(0.0f),
_timeWithoutTalking(0.0f),
_pitchTweak(0.f),
_yawTweak(0.f),
_rollTweak(0.f),
_deltaPitch(0.f),
_deltaYaw(0.f),
_deltaRoll(0.f),
_deltaLeanSideways(0.f),
_deltaLeanForward(0.f),
_isCameraMoving(false),
_faceModel(this)
{
@ -50,13 +52,12 @@ void Head::init() {
}
void Head::reset() {
_yaw = _pitch = _roll = 0.0f;
_baseYaw = _basePitch = _baseRoll = 0.0f;
_leanForward = _leanSideways = 0.0f;
_faceModel.reset();
}
void Head::simulate(float deltaTime, bool isMine, bool billboard) {
// Update audio trailing average for rendering facial animations
Faceshift* faceshift = Application::getInstance()->getFaceshift();
Visage* visage = Application::getInstance()->getVisage();
@ -165,6 +166,19 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
_eyePosition = calculateAverageEyePosition();
}
void Head::relaxLean(float deltaTime) {
// restore rotation, lean to neutral positions
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds
float relaxationFactor = 1.f - glm::min(deltaTime / LEAN_RELAXATION_PERIOD, 1.f);
_deltaYaw *= relaxationFactor;
_deltaPitch *= relaxationFactor;
_deltaRoll *= relaxationFactor;
_leanSideways *= relaxationFactor;
_leanForward *= relaxationFactor;
_deltaLeanSideways *= relaxationFactor;
_deltaLeanForward *= relaxationFactor;
}
void Head::render(float alpha, bool forShadowMap) {
if (_faceModel.render(alpha, forShadowMap) && _renderLookatVectors) {
renderLookatVectors(_leftEyePosition, _rightEyePosition, _lookAtPosition);
@ -178,14 +192,14 @@ void Head::setScale (float scale) {
_scale = scale;
}
glm::quat Head::getTweakedOrientation() const {
glm::quat Head::getFinalOrientation() const {
return _owningAvatar->getOrientation() * glm::quat(glm::radians(
glm::vec3(getTweakedPitch(), getTweakedYaw(), getTweakedRoll() )));
glm::vec3(getFinalPitch(), getFinalYaw(), getFinalRoll() )));
}
glm::quat Head::getCameraOrientation () const {
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_pitch, 0.f, 0.0f)));
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.f, 0.0f)));
}
glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
@ -197,16 +211,21 @@ glm::vec3 Head::getScalePivot() const {
return _faceModel.isActive() ? _faceModel.getTranslation() : _position;
}
float Head::getTweakedYaw() const {
return glm::clamp(_yaw + _yawTweak, MIN_HEAD_YAW, MAX_HEAD_YAW);
float Head::getFinalYaw() const {
return glm::clamp(_baseYaw + _deltaYaw, MIN_HEAD_YAW, MAX_HEAD_YAW);
}
float Head::getTweakedPitch() const {
return glm::clamp(_pitch + _pitchTweak, MIN_HEAD_PITCH, MAX_HEAD_PITCH);
float Head::getFinalPitch() const {
return glm::clamp(_basePitch + _deltaPitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH);
}
float Head::getTweakedRoll() const {
return glm::clamp(_roll + _rollTweak, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
float Head::getFinalRoll() const {
return glm::clamp(_baseRoll + _deltaRoll, MIN_HEAD_ROLL, MAX_HEAD_ROLL);
}
void Head::addLeanDeltas(float sideways, float forward) {
_deltaLeanSideways += sideways;
_deltaLeanForward += forward;
}
void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosition, glm::vec3 lookatPosition) {

View file

@ -44,9 +44,15 @@ public:
void setAverageLoudness(float averageLoudness) { _averageLoudness = averageLoudness; }
void setReturnToCenter (bool returnHeadToCenter) { _returnHeadToCenter = returnHeadToCenter; }
void setRenderLookatVectors(bool onOff) { _renderLookatVectors = onOff; }
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
void setLeanForward(float leanForward) { _leanForward = leanForward; }
glm::quat getTweakedOrientation() const;
/// \return orientationBody * orientationBase+Delta
glm::quat getFinalOrientation() const;
/// \return orientationBody * orientationBasePitch
glm::quat getCameraOrientation () const;
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; }
@ -57,6 +63,10 @@ public:
glm::vec3 getRightDirection() const { return getOrientation() * IDENTITY_RIGHT; }
glm::vec3 getUpDirection() const { return getOrientation() * IDENTITY_UP; }
glm::vec3 getFrontDirection() const { return getOrientation() * IDENTITY_FRONT; }
float getLeanSideways() const { return _leanSideways; }
float getLeanForward() const { return _leanForward; }
float getFinalLeanSideways() const { return _leanSideways + _deltaLeanSideways; }
float getFinalLeanForward() const { return _leanForward + _deltaLeanForward; }
glm::quat getEyeRotation(const glm::vec3& eyePosition) const;
@ -67,21 +77,24 @@ public:
float getAverageLoudness() const { return _averageLoudness; }
glm::vec3 calculateAverageEyePosition() { return _leftEyePosition + (_rightEyePosition - _leftEyePosition ) * ONE_HALF; }
/// Returns the point about which scaling occurs.
/// \return the point about which scaling occurs.
glm::vec3 getScalePivot() const;
void setPitchTweak(float pitch) { _pitchTweak = pitch; }
float getPitchTweak() const { return _pitchTweak; }
void setDeltaPitch(float pitch) { _deltaPitch = pitch; }
float getDeltaPitch() const { return _deltaPitch; }
void setYawTweak(float yaw) { _yawTweak = yaw; }
float getYawTweak() const { return _yawTweak; }
void setDeltaYaw(float yaw) { _deltaYaw = yaw; }
float getDeltaYaw() const { return _deltaYaw; }
void setRollTweak(float roll) { _rollTweak = roll; }
float getRollTweak() const { return _rollTweak; }
void setDeltaRoll(float roll) { _deltaRoll = roll; }
float getDeltaRoll() const { return _deltaRoll; }
virtual float getTweakedPitch() const;
virtual float getTweakedYaw() const;
virtual float getTweakedRoll() const;
virtual float getFinalPitch() const;
virtual float getFinalYaw() const;
virtual float getFinalRoll() const;
void relaxLean(float deltaTime);
void addLeanDeltas(float sideways, float forward);
private:
// disallow copies of the Head, copy of owning Avatar is disallowed too
@ -106,10 +119,14 @@ private:
float _rightEyeBlinkVelocity;
float _timeWithoutTalking;
// tweaked angles affect the rendered head, but not the camera
float _pitchTweak;
float _yawTweak;
float _rollTweak;
// delta angles for local head rotation (driven by hardware input)
float _deltaPitch;
float _deltaYaw;
float _deltaRoll;
// delta lean angles for lean perturbations (driven by collisions)
float _deltaLeanSideways;
float _deltaLeanForward;
bool _isCameraMoving;
FaceModel _faceModel;

View file

@ -94,7 +94,13 @@ void MyAvatar::setMoveTarget(const glm::vec3 moveTarget) {
}
void MyAvatar::update(float deltaTime) {
Head* head = getHead();
head->relaxLean(deltaTime);
updateFromGyros(deltaTime);
if (Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
// Faceshift drive is enabled, set the avatar drive based on the head position
moveWithLean();
}
// Update head mouse from faceshift if active
Faceshift* faceshift = Application::getInstance()->getFaceshift();
@ -112,15 +118,14 @@ void MyAvatar::update(float deltaTime) {
//_headMouseY = glm::clamp(_headMouseY, 0, _glWidget->height());
}
Head* head = getHead();
if (OculusManager::isConnected()) {
float yaw, pitch, roll; // these angles will be in radians
OculusManager::getEulerAngles(yaw, pitch, roll);
// but these euler angles are stored in degrees
head->setYaw(yaw * DEGREES_PER_RADIAN);
head->setPitch(pitch * DEGREES_PER_RADIAN);
head->setRoll(roll * DEGREES_PER_RADIAN);
head->setBaseYaw(yaw * DEGREES_PER_RADIAN);
head->setBasePitch(pitch * DEGREES_PER_RADIAN);
head->setBaseRoll(roll * DEGREES_PER_RADIAN);
}
// Get audio loudness data from audio input device
@ -230,7 +235,7 @@ void MyAvatar::simulate(float deltaTime) {
if (!Application::getInstance()->getFaceshift()->isActive() && OculusManager::isConnected() &&
fabsf(forwardAcceleration) > OCULUS_ACCELERATION_PULL_THRESHOLD &&
fabs(getHead()->getYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) {
fabs(getHead()->getBaseYaw()) > OCULUS_YAW_OFFSET_THRESHOLD) {
// if we're wearing the oculus
// and this acceleration is above the pull threshold
@ -240,7 +245,7 @@ void MyAvatar::simulate(float deltaTime) {
_bodyYaw = getAbsoluteHeadYaw();
// set the head yaw to zero for this draw
getHead()->setYaw(0);
getHead()->setBaseYaw(0);
// correct the oculus yaw offset
OculusManager::updateYawOffset();
@ -361,26 +366,16 @@ void MyAvatar::updateFromGyros(float deltaTime) {
}
}
}
} else {
// restore rotation, lean to neutral positions
const float RESTORE_PERIOD = 0.25f; // seconds
float restorePercentage = glm::clamp(deltaTime/RESTORE_PERIOD, 0.f, 1.f);
head->setPitchTweak(glm::mix(head->getPitchTweak(), 0.0f, restorePercentage));
head->setYawTweak(glm::mix(head->getYawTweak(), 0.0f, restorePercentage));
head->setRollTweak(glm::mix(head->getRollTweak(), 0.0f, restorePercentage));
head->setLeanSideways(glm::mix(head->getLeanSideways(), 0.0f, restorePercentage));
head->setLeanForward(glm::mix(head->getLeanForward(), 0.0f, restorePercentage));
return;
}
}
// Set the rotation of the avatar's head (as seen by others, not affecting view frustum)
// to be scaled. Pitch is greater to emphasize nodding behavior / synchrony.
const float AVATAR_HEAD_PITCH_MAGNIFY = 1.0f;
const float AVATAR_HEAD_YAW_MAGNIFY = 1.0f;
const float AVATAR_HEAD_ROLL_MAGNIFY = 1.0f;
head->setPitchTweak(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
head->setYawTweak(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
head->setRollTweak(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
head->setDeltaPitch(estimatedRotation.x * AVATAR_HEAD_PITCH_MAGNIFY);
head->setDeltaYaw(estimatedRotation.y * AVATAR_HEAD_YAW_MAGNIFY);
head->setDeltaRoll(estimatedRotation.z * AVATAR_HEAD_ROLL_MAGNIFY);
// Update torso lean distance based on accelerometer data
const float TORSO_LENGTH = 0.5f;
@ -390,13 +385,11 @@ void MyAvatar::updateFromGyros(float deltaTime) {
-MAX_LEAN, MAX_LEAN));
head->setLeanForward(glm::clamp(glm::degrees(atanf(relativePosition.z * _leanScale / TORSO_LENGTH)),
-MAX_LEAN, MAX_LEAN));
}
// if Faceshift drive is enabled, set the avatar drive based on the head position
if (!Menu::getInstance()->isOptionChecked(MenuOption::MoveWithLean)) {
return;
}
void MyAvatar::moveWithLean() {
// Move with Lean by applying thrust proportional to leaning
Head* head = getHead();
glm::quat orientation = head->getCameraOrientation();
glm::vec3 front = orientation * IDENTITY_FRONT;
glm::vec3 right = orientation * IDENTITY_RIGHT;
@ -506,7 +499,7 @@ void MyAvatar::saveData(QSettings* settings) {
settings->setValue("bodyPitch", _bodyPitch);
settings->setValue("bodyRoll", _bodyRoll);
settings->setValue("headPitch", getHead()->getPitch());
settings->setValue("headPitch", getHead()->getBasePitch());
settings->setValue("position_x", _position.x);
settings->setValue("position_y", _position.y);
@ -532,7 +525,7 @@ void MyAvatar::loadData(QSettings* settings) {
_bodyPitch = loadSetting(settings, "bodyPitch", 0.0f);
_bodyRoll = loadSetting(settings, "bodyRoll", 0.0f);
getHead()->setPitch(loadSetting(settings, "headPitch", 0.0f));
getHead()->setBasePitch(loadSetting(settings, "headPitch", 0.0f));
_position.x = loadSetting(settings, "position_x", 0.0f);
_position.y = loadSetting(settings, "position_y", 0.0f);
@ -575,9 +568,9 @@ void MyAvatar::orbit(const glm::vec3& position, int deltaX, int deltaY) {
setOrientation(orientation);
// then vertically
float oldPitch = getHead()->getPitch();
getHead()->setPitch(oldPitch - deltaY * ANGULAR_SCALE);
rotation = glm::angleAxis(glm::radians((getHead()->getPitch() - oldPitch)), orientation * IDENTITY_RIGHT);
float oldPitch = getHead()->getBasePitch();
getHead()->setBasePitch(oldPitch - deltaY * ANGULAR_SCALE);
rotation = glm::angleAxis(glm::radians((getHead()->getBasePitch() - oldPitch)), orientation * IDENTITY_RIGHT);
setPosition(position + rotation * (getPosition() - position));
}
@ -683,7 +676,7 @@ void MyAvatar::updateThrust(float deltaTime) {
_thrust -= _driveKeys[DOWN] * _scale * THRUST_MAG_DOWN * _thrustMultiplier * deltaTime * up;
_bodyYawDelta -= _driveKeys[ROT_RIGHT] * YAW_SPEED * deltaTime;
_bodyYawDelta += _driveKeys[ROT_LEFT] * YAW_SPEED * deltaTime;
getHead()->setPitch(getHead()->getPitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
getHead()->setBasePitch(getHead()->getBasePitch() + (_driveKeys[ROT_UP] - _driveKeys[ROT_DOWN]) * PITCH_SPEED * deltaTime);
// If thrust keys are being held down, slowly increase thrust to allow reaching great speeds
if (_driveKeys[FWD] || _driveKeys[BACK] || _driveKeys[RIGHT] || _driveKeys[LEFT] || _driveKeys[UP] || _driveKeys[DOWN]) {
@ -1153,3 +1146,21 @@ void MyAvatar::goToLocationFromResponse(const QJsonObject& jsonObject) {
}
}
void MyAvatar::applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration) {
glm::vec3 leverAxis = contactPoint - getPosition();
float leverLength = glm::length(leverAxis);
if (leverLength > EPSILON) {
// compute lean perturbation angles
glm::quat bodyRotation = getOrientation();
glm::vec3 xAxis = bodyRotation * glm::vec3(1.f, 0.f, 0.f);
glm::vec3 zAxis = bodyRotation * glm::vec3(0.f, 0.f, 1.f);
leverAxis = leverAxis / leverLength;
glm::vec3 effectivePenetration = penetration - glm::dot(penetration, leverAxis) * leverAxis;
// use the small-angle approximation for sine
float sideways = - glm::dot(effectivePenetration, xAxis) / leverLength;
float forward = glm::dot(effectivePenetration, zAxis) / leverLength;
getHead()->addLeanDeltas(sideways, forward);
}
}

View file

@ -34,6 +34,7 @@ public:
void update(float deltaTime);
void simulate(float deltaTime);
void updateFromGyros(float deltaTime);
void moveWithLean();
void render(const glm::vec3& cameraPosition, RenderMode renderMode = NORMAL_RENDER_MODE);
void renderBody(RenderMode renderMode);
@ -87,6 +88,9 @@ public:
virtual void clearJointData(int index);
virtual void setFaceModelURL(const QUrl& faceModelURL);
virtual void setSkeletonModelURL(const QUrl& skeletonModelURL);
void applyCollision(const glm::vec3& contactPoint, const glm::vec3& penetration);
public slots:
void goHome();
void increaseSize();

View file

@ -72,11 +72,15 @@ void SkeletonModel::getHandShapes(int jointIndex, QVector<const Shape*>& shapes)
const FBXGeometry& geometry = _geometry->getFBXGeometry();
for (int i = 0; i < _jointStates.size(); i++) {
const FBXJoint& joint = geometry.joints[i];
int parentIndex = joint.parentIndex;
if (i == jointIndex) {
// this shape is the hand
shapes.push_back(_shapes[i]);
if (parentIndex != -1) {
// also add the forearm
shapes.push_back(_shapes[parentIndex]);
}
} else {
int parentIndex = joint.parentIndex;
while (parentIndex != -1) {
if (parentIndex == jointIndex) {
// this shape is a child of the hand
@ -146,7 +150,7 @@ void SkeletonModel::applyPalmData(int jointIndex, const QVector<int>& fingerJoin
direction += fingerVector / length;
}
fingerVector = glm::inverse(palmRotation) * fingerVector * -sign;
IndexValue indexValue = { int(i), atan2f(fingerVector.z, fingerVector.x) };
IndexValue indexValue = { (int)i, atan2f(fingerVector.z, fingerVector.x) };
fingerIndices.append(indexValue);
}
qSort(fingerIndices.begin(), fingerIndices.end());
@ -199,8 +203,8 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
glm::mat3 axes = glm::mat3_cast(_rotation);
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.transform * glm::translate(state.translation) *
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getLeanSideways(),
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getLeanForward(),
state.rotation = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
glm::normalize(inverse * axes[2])) * glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanForward(),
glm::normalize(inverse * axes[0])) * joint.rotation;
}

View file

@ -1594,7 +1594,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
int numVertices = extracted.mesh.vertices.size();
jointShapeInfo.numVertices = numVertices;
if (numVertices > 0) {
averageVertex /= float(jointShapeInfo.numVertices);
averageVertex /= (float)jointShapeInfo.numVertices;
float averageRadius = 0.f;
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
averageRadius += glm::distance(vertex, averageVertex);
@ -1625,7 +1625,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} else {
// collide the joint like a sphere
if (jointShapeInfo.numVertices > 0) {
jointShapeInfo.averageVertex /= float(jointShapeInfo.numVertices);
jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices;
joint.shapePosition = jointShapeInfo.averageVertex;
} else {
joint.shapePosition = glm::vec3(0.f);
@ -1635,7 +1635,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
&& jointShapeInfo.numVertices > 0) {
// the bone projection algorithm was not able to compute the joint radius
// so we use an alternative measure
jointShapeInfo.averageRadius /= float(jointShapeInfo.numVertices);
jointShapeInfo.averageRadius /= (float)jointShapeInfo.numVertices;
joint.boneRadius = jointShapeInfo.averageRadius;
}
}

View file

@ -31,11 +31,11 @@ void GeometryCache::renderHemisphere(int slices, int stacks) {
GLfloat* vertexData = new GLfloat[vertices * 3];
GLfloat* vertex = vertexData;
for (int i = 0; i < stacks - 1; i++) {
float phi = PI_OVER_TWO * float(i) / float(stacks - 1);
float phi = PI_OVER_TWO * (float)i / (float)(stacks - 1);
float z = sinf(phi), radius = cosf(phi);
for (int j = 0; j < slices; j++) {
float theta = TWO_PI * float(j) / float(slices);
float theta = TWO_PI * (float)j / (float)slices;
*(vertex++) = sinf(theta) * radius;
*(vertex++) = cosf(theta) * radius;
@ -181,7 +181,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
float y = (float)i / (stacks - 1);
for (int j = 0; j <= slices; j++) {
float theta = 3.f * PI_OVER_TWO + PI * float(j) / float(slices);
float theta = 3.f * PI_OVER_TWO + PI * (float)j / (float)slices;
//normals
*(vertex++) = sinf(theta);

View file

@ -160,7 +160,7 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) {
// Center of coordinate system -> upper left of bar
glPushMatrix();
glTranslatef(float(barX), float(y), 0.0f);
glTranslatef((float)barX, (float)y, 0.0f);
// Render captions
setColorRGBA(COLOR_TEXT);
@ -202,7 +202,7 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) {
// Render scale indicators
setColorRGBA(COLOR_INDICATOR);
for (int j = NUMBER_OF_MARKERS; --j > 0;) {
renderVerticalLine(int(barWidth * j / NUMBER_OF_MARKERS), 0, h);
renderVerticalLine((barWidth * j) / NUMBER_OF_MARKERS, 0, h);
}
// Render bars
@ -210,8 +210,8 @@ void BandwidthMeter::render(int screenWidth, int screenHeight) {
for (size_t i = 0; i < N_CHANNELS; ++i) {
ChannelIndex chIdx = ChannelIndex(i);
int wIn = int(barWidth * inputStream(chIdx).getValue() * UNIT_SCALE / scaleMax);
int wOut = int(barWidth * outputStream(chIdx).getValue() * UNIT_SCALE / scaleMax);
int wIn = (int)(barWidth * inputStream(chIdx).getValue() * UNIT_SCALE / scaleMax);
int wOut = (int)(barWidth * outputStream(chIdx).getValue() * UNIT_SCALE / scaleMax);
setColorRGBA(channelInfo(chIdx).colorRGBA);

View file

@ -6,13 +6,12 @@
// Copyright (c) 2014 High Fidelity, Inc. All rights reserved.
//
#include <QFormLayout>
#include <QGridLayout>
#include <QFrame>
#include <QLayoutItem>
#include <QPalette>
#include <QScrollBar>
#include <QSizePolicy>
#include <QTextDocument>
#include <QTimer>
#include "Application.h"
@ -31,17 +30,18 @@ ChatWindow::ChatWindow() :
ui(new Ui::ChatWindow),
numMessagesAfterLastTimeStamp(0)
{
QWidget* widget = new QWidget();
setWidget(widget);
ui->setupUi(widget);
ui->setupUi(this);
// remove the title bar (see the Qt docs on setTitleBarWidget)
setTitleBarWidget(new QWidget());
FlowLayout* flowLayout = new FlowLayout(0, 4, 4);
ui->usersWidget->setLayout(flowLayout);
ui->messagePlainTextEdit->installEventFilter(this);
ui->messagesGridLayout->setColumnStretch(0, 1);
ui->messagesGridLayout->setColumnStretch(1, 3);
ui->closeButton->hide();
ui->messagePlainTextEdit->installEventFilter(this);
#ifdef HAVE_QXMPP
const QXmppClient& xmppClient = XmppClient::getInstance().getXMPPClient();
@ -76,41 +76,48 @@ ChatWindow::~ChatWindow() {
}
void ChatWindow::keyPressEvent(QKeyEvent* event) {
QWidget::keyPressEvent(event);
QDockWidget::keyPressEvent(event);
if (event->key() == Qt::Key_Escape) {
hide();
}
}
void ChatWindow::showEvent(QShowEvent* event) {
QWidget::showEvent(event);
QDockWidget::showEvent(event);
if (!event->spontaneous()) {
activateWindow();
ui->messagePlainTextEdit->setFocus();
}
}
bool ChatWindow::eventFilter(QObject* sender, QEvent* event) {
Q_UNUSED(sender);
if (event->type() != QEvent::KeyPress) {
return false;
}
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) &&
(keyEvent->modifiers() & Qt::ShiftModifier) == 0) {
QString messageText = ui->messagePlainTextEdit->document()->toPlainText().trimmed();
if (!messageText.isEmpty()) {
#ifdef HAVE_QXMPP
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
QXmppMessage message;
message.setTo(publicChatRoom->jid());
message.setType(QXmppMessage::GroupChat);
message.setBody(messageText);
XmppClient::getInstance().getXMPPClient().sendPacket(message);
#endif
ui->messagePlainTextEdit->document()->clear();
if (sender == ui->messagePlainTextEdit) {
if (event->type() != QEvent::KeyPress) {
return false;
}
return true;
QKeyEvent* keyEvent = static_cast<QKeyEvent*>(event);
if ((keyEvent->key() == Qt::Key_Return || keyEvent->key() == Qt::Key_Enter) &&
(keyEvent->modifiers() & Qt::ShiftModifier) == 0) {
QString messageText = ui->messagePlainTextEdit->document()->toPlainText().trimmed();
if (!messageText.isEmpty()) {
#ifdef HAVE_QXMPP
const QXmppMucRoom* publicChatRoom = XmppClient::getInstance().getPublicChatRoom();
QXmppMessage message;
message.setTo(publicChatRoom->jid());
message.setType(QXmppMessage::GroupChat);
message.setBody(messageText);
XmppClient::getInstance().getXMPPClient().sendPacket(message);
#endif
ui->messagePlainTextEdit->document()->clear();
}
return true;
}
} else {
if (event->type() != QEvent::MouseButtonRelease) {
return false;
}
QString user = sender->property("user").toString();
Menu::getInstance()->goToUser(user);
}
return false;
}
@ -138,8 +145,9 @@ void ChatWindow::addTimeStamp() {
timeLabel->setStyleSheet("color: palette(shadow);"
"background-color: palette(highlight);"
"padding: 4px;");
timeLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
timeLabel->setAlignment(Qt::AlignHCenter);
ui->messagesFormLayout->addRow(timeLabel);
ui->messagesGridLayout->addWidget(timeLabel, ui->messagesGridLayout->rowCount(), 0, 1, 2);
numMessagesAfterLastTimeStamp = 0;
}
}
@ -187,13 +195,21 @@ void ChatWindow::participantsChanged() {
delete item;
}
foreach (const QString& participant, participants) {
QLabel* userLabel = new QLabel(getParticipantName(participant));
QString participantName = getParticipantName(participant);
QLabel* userLabel = new QLabel();
userLabel->setText(participantName);
userLabel->setStyleSheet("background-color: palette(light);"
"border-radius: 5px;"
"color: #267077;"
"padding: 2px;"
"padding-top: 3px;"
"padding-right: 2px;"
"padding-bottom: 2px;"
"padding-left: 2px;"
"border: 1px solid palette(shadow);"
"font-weight: bold");
userLabel->setProperty("user", participantName);
userLabel->setCursor(Qt::PointingHandCursor);
userLabel->installEventFilter(this);
ui->usersWidget->layout()->addWidget(userLabel);
}
}
@ -204,19 +220,25 @@ void ChatWindow::messageReceived(const QXmppMessage& message) {
}
QLabel* userLabel = new QLabel(getParticipantName(message.from()));
userLabel->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
userLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
userLabel->setStyleSheet("padding: 2px; font-weight: bold");
userLabel->setAlignment(Qt::AlignTop);
userLabel->setAlignment(Qt::AlignTop | Qt::AlignRight);
QLabel* messageLabel = new QLabel(message.body().replace(regexLinks, "<a href=\"\\1\">\\1</a>"));
messageLabel->setWordWrap(true);
messageLabel->setTextInteractionFlags(Qt::TextBrowserInteraction);
messageLabel->setOpenExternalLinks(true);
messageLabel->setStyleSheet("padding: 2px; margin-right: 20px");
messageLabel->setAlignment(Qt::AlignTop);
messageLabel->setStyleSheet("padding-bottom: 2px; padding-right: 2px; padding-top: 2px; padding-right: 20px");
messageLabel->setAlignment(Qt::AlignTop | Qt::AlignLeft);
ui->messagesFormLayout->addRow(userLabel, messageLabel);
ui->messagesFormLayout->parentWidget()->updateGeometry();
if (getParticipantName(message.from()) == AccountManager::getInstance().getUsername()) {
userLabel->setStyleSheet(userLabel->styleSheet() + "; background-color: #e1e8ea");
messageLabel->setStyleSheet(messageLabel->styleSheet() + "; background-color: #e1e8ea");
}
ui->messagesGridLayout->addWidget(userLabel, ui->messagesGridLayout->rowCount(), 0);
ui->messagesGridLayout->addWidget(messageLabel, ui->messagesGridLayout->rowCount() - 1, 1);
ui->messagesGridLayout->parentWidget()->updateGeometry();
Application::processEvents();
QScrollBar* verticalScrollBar = ui->messagesScrollArea->verticalScrollBar();
verticalScrollBar->setSliderPosition(verticalScrollBar->maximum());

View file

@ -127,7 +127,7 @@ void Oscilloscope::render(int x, int y) {
}
// fetch low pass factor (and convert to fix point) / downsample factor
int lowPassFixPt = -int(std::numeric_limits<short>::min()) * _lowPassCoeff;
int lowPassFixPt = -(int)(std::numeric_limits<short>::min()) * _lowPassCoeff;
unsigned downsample = _downsampleRatio;
// keep half of the buffer for writing and ensure an even vertex count
unsigned usedWidth = min(_width, MAX_SAMPLES_PER_CHANNEL / (downsample * 2)) & ~1u;
@ -141,7 +141,7 @@ void Oscilloscope::render(int x, int y) {
short const* inPtr = _samples + _writePos[ch];
short* outPtr = _vertices + MAX_COORDS_PER_CHANNEL * ch;
int sample = 0, x = usedWidth;
for (int i = int(usedSamples); --i >= 0 ;) {
for (int i = (int)usedSamples; --i >= 0 ;) {
if (inPtr == basePtr) {
// handle boundary, reading the circular sample buffer
inPtr = endPtr;

View file

@ -1,7 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>ChatWindow</class>
<widget class="QWidget" name="ChatWindow">
<widget class="QDockWidget" name="ChatWindow">
<property name="geometry">
<rect>
<x>0</x>
@ -13,180 +13,188 @@
<property name="minimumSize">
<size>
<width>400</width>
<height>0</height>
<height>238</height>
</size>
</property>
<property name="windowTitle">
<string>Chat</string>
</property>
<property name="styleSheet">
<string notr="true">font-family: Helvetica, Arial, sans-serif;</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>8</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="connectingToXMPPLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connecting to XMPP...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="numOnlineLabel">
<property name="features">
<set>QDockWidget::NoDockWidgetFeatures</set>
</property>
<property name="allowedAreas">
<set>Qt::NoDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>Chat</string>
</property>
<widget class="QWidget" name="dockWidgetContents">
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>8</number>
</property>
<property name="topMargin">
<number>8</number>
</property>
<property name="rightMargin">
<number>8</number>
</property>
<property name="bottomMargin">
<number>8</number>
</property>
<item>
<widget class="QLabel" name="connectingToXMPPLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Connecting to XMPP...</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="horizontalLayout">
<item>
<widget class="QLabel" name="numOnlineLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">font-weight: bold; color: palette(shadow); margin-bottom: 4px;</string>
</property>
<property name="text">
<string> online now:</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/images/close.svg</normaloff>:/images/close.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="usersWidget" native="true"/>
</item>
<item>
<widget class="QScrollArea" name="messagesScrollArea">
<property name="styleSheet">
<string notr="true">margin-top: 12px;</string>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>382</width>
<height>16</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">font-weight: bold; color: palette(shadow); margin-bottom: 4px;</string>
</property>
<property name="text">
<string> online now:</string>
<string notr="true">margin-top: 0px;</string>
</property>
<layout class="QGridLayout" name="messagesGridLayout">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>0</number>
</property>
</layout>
</widget>
</item>
<item>
<widget class="QPushButton" name="closeButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="maximumSize">
<size>
<width>16</width>
<height>16</height>
</size>
</property>
<property name="focusPolicy">
<enum>Qt::NoFocus</enum>
</property>
<property name="text">
<string/>
</property>
<property name="icon">
<iconset resource="../resources/resources.qrc">
<normaloff>:/images/close.svg</normaloff>:/images/close.svg</iconset>
</property>
<property name="flat">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="QWidget" name="usersWidget" native="true"/>
</item>
<item>
<widget class="QScrollArea" name="messagesScrollArea">
<property name="styleSheet">
<string notr="true">margin-top: 12px;</string>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>358</width>
<height>464</height>
</rect>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="messagePlainTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">margin-top: 0px;</string>
<string notr="true">border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px;</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
<layout class="QFormLayout" name="messagesFormLayout">
<property name="fieldGrowthPolicy">
<enum>QFormLayout::AllNonFixedFieldsGrow</enum>
</property>
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>4</number>
</property>
<property name="topMargin">
<number>4</number>
</property>
<property name="rightMargin">
<number>4</number>
</property>
<property name="bottomMargin">
<number>4</number>
</property>
</layout>
</widget>
</widget>
</item>
<item>
<widget class="QPlainTextEdit" name="messagePlainTextEdit">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>60</height>
</size>
</property>
<property name="styleSheet">
<string notr="true">border-color: palette(dark); border-style: solid; border-left-width: 1px; border-right-width: 1px; border-bottom-width: 1px;</string>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="horizontalScrollBarPolicy">
<enum>Qt::ScrollBarAlwaysOff</enum>
</property>
<property name="sizeAdjustPolicy">
<enum>QAbstractScrollArea::AdjustToContents</enum>
</property>
<property name="tabChangesFocus">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</item>
</layout>
</widget>
</widget>
<tabstops>
<tabstop>messagePlainTextEdit</tabstop>

View file

@ -93,9 +93,9 @@ QByteArray AvatarData::toByteArray() {
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _targetScale);
// Head rotation (NOTE: This needs to become a quaternion to save two bytes)
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedYaw());
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedPitch());
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getTweakedRoll());
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalYaw());
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalPitch());
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _headData->getFinalRoll());
// Head lean X,Z (head lateral and fwd/back motion relative to torso)
memcpy(destinationBuffer, &_headData->_leanSideways, sizeof(_headData->_leanSideways));
@ -288,9 +288,9 @@ int AvatarData::parseDataAtOffset(const QByteArray& packet, int offset) {
}
return maxAvailableSize;
}
_headData->setYaw(headYaw);
_headData->setPitch(headPitch);
_headData->setRoll(headRoll);
_headData->setBaseYaw(headYaw);
_headData->setBasePitch(headPitch);
_headData->setBaseRoll(headRoll);
} // 6 bytes
// Head lean (relative to pelvis)

View file

@ -128,8 +128,8 @@ public:
void setHeadOrientation(const glm::quat& orientation) { _headData->setOrientation(orientation); }
// access to Head().set/getMousePitch (degrees)
float getHeadPitch() const { return _headData->getPitch(); }
void setHeadPitch(float value) { _headData->setPitch(value); };
float getHeadPitch() const { return _headData->getBasePitch(); }
void setHeadPitch(float value) { _headData->setBasePitch(value); };
// access to Head().set/getAverageLoudness
float getAudioLoudness() const { return _headData->getAudioLoudness(); }

View file

@ -14,9 +14,9 @@
#include "HeadData.h"
HeadData::HeadData(AvatarData* owningAvatar) :
_yaw(0.0f),
_pitch(0.0f),
_roll(0.0f),
_baseYaw(0.0f),
_basePitch(0.0f),
_baseRoll(0.0f),
_leanSideways(0.0f),
_leanForward(0.0f),
_lookAtPosition(0.0f, 0.0f, 0.0f),
@ -32,7 +32,7 @@ HeadData::HeadData(AvatarData* owningAvatar) :
}
glm::quat HeadData::getOrientation() const {
return _owningAvatar->getOrientation() * glm::quat(glm::radians(glm::vec3(_pitch, _yaw, _roll)));
return _owningAvatar->getOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, _baseYaw, _baseRoll)));
}
void HeadData::setOrientation(const glm::quat& orientation) {
@ -44,27 +44,20 @@ void HeadData::setOrientation(const glm::quat& orientation) {
// the rest goes to the head
glm::vec3 eulers = glm::degrees(safeEulerAngles(glm::inverse(bodyOrientation) * orientation));
_pitch = eulers.x;
_yaw = eulers.y;
_roll = eulers.z;
_basePitch = eulers.x;
_baseYaw = eulers.y;
_baseRoll = eulers.z;
}
void HeadData::addYaw(float yaw) {
setYaw(_yaw + yaw);
setBaseYaw(_baseYaw + yaw);
}
void HeadData::addPitch(float pitch) {
setPitch(_pitch + pitch);
setBasePitch(_basePitch + pitch);
}
void HeadData::addRoll(float roll) {
setRoll(_roll + roll);
}
void HeadData::addLean(float sideways, float forwards) {
// Add lean as impulse
_leanSideways += sideways;
_leanForward += forwards;
setBaseRoll(_baseRoll + roll);
}

View file

@ -32,19 +32,15 @@ public:
virtual ~HeadData() { };
// degrees
float getLeanSideways() const { return _leanSideways; }
void setLeanSideways(float leanSideways) { _leanSideways = leanSideways; }
float getLeanForward() const { return _leanForward; }
void setLeanForward(float leanForward) { _leanForward = leanForward; }
float getYaw() const { return _yaw; }
void setYaw(float yaw) { _yaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); }
float getPitch() const { return _pitch; }
void setPitch(float pitch) { _pitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); }
float getRoll() const { return _roll; }
void setRoll(float roll) { _roll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); }
virtual float getTweakedYaw() const { return _yaw; }
virtual float getTweakedPitch() const { return _pitch; }
virtual float getTweakedRoll() const { return _roll; }
float getBaseYaw() const { return _baseYaw; }
void setBaseYaw(float yaw) { _baseYaw = glm::clamp(yaw, MIN_HEAD_YAW, MAX_HEAD_YAW); }
float getBasePitch() const { return _basePitch; }
void setBasePitch(float pitch) { _basePitch = glm::clamp(pitch, MIN_HEAD_PITCH, MAX_HEAD_PITCH); }
float getBaseRoll() const { return _baseRoll; }
void setBaseRoll(float roll) { _baseRoll = glm::clamp(roll, MIN_HEAD_ROLL, MAX_HEAD_ROLL); }
virtual float getFinalYaw() const { return _baseYaw; }
virtual float getFinalPitch() const { return _basePitch; }
virtual float getFinalRoll() const { return _baseRoll; }
glm::quat getOrientation() const;
void setOrientation(const glm::quat& orientation);
@ -64,7 +60,6 @@ public:
void addYaw(float yaw);
void addPitch(float pitch);
void addRoll(float roll);
void addLean(float sideways, float forwards);
const glm::vec3& getLookAtPosition() const { return _lookAtPosition; }
void setLookAtPosition(const glm::vec3& lookAtPosition) { _lookAtPosition = lookAtPosition; }
@ -73,9 +68,9 @@ public:
protected:
// degrees
float _yaw;
float _pitch;
float _roll;
float _baseYaw;
float _basePitch;
float _baseRoll;
float _leanSideways;
float _leanForward;

View file

@ -1096,7 +1096,7 @@ QScriptValue ScriptedMetavoxelGuide::visit(QScriptContext* context, QScriptEngin
QScriptValue minimum = infoValue.property(guide->_minimumHandle);
MetavoxelInfo info = {
glm::vec3(minimum.property(0).toNumber(), minimum.property(1).toNumber(), minimum.property(2).toNumber()),
float(infoValue.property(guide->_sizeHandle).toNumber()), guide->_visitation->info.inputValues,
(float)infoValue.property(guide->_sizeHandle).toNumber(), guide->_visitation->info.inputValues,
guide->_visitation->info.outputValues, infoValue.property(guide->_isLeafHandle).toBool() };
// extract and convert the values provided by the script

View file

@ -20,18 +20,15 @@ ThreadedAssignment::ThreadedAssignment(const QByteArray& packet) :
}
void ThreadedAssignment::deleteLater() {
// move the NodeList back to the QCoreApplication instance's thread
NodeList::getInstance()->moveToThread(QCoreApplication::instance()->thread());
QObject::deleteLater();
}
void ThreadedAssignment::setFinished(bool isFinished) {
_isFinished = isFinished;
if (_isFinished) {
aboutToFinish();
emit finished();
// move the NodeList back to the QCoreApplication instance's thread
NodeList::getInstance()->moveToThread(QCoreApplication::instance()->thread());
}
}

View file

@ -9,6 +9,8 @@
#ifndef __hifi__ThreadedAssignment__
#define __hifi__ThreadedAssignment__
#include <QtCore/QSharedPointer>
#include "Assignment.h"
class ThreadedAssignment : public Assignment {
@ -22,7 +24,6 @@ public:
public slots:
/// threaded run of assignment
virtual void run() = 0;
virtual void deleteLater();
virtual void readPendingDatagrams() = 0;
virtual void sendStatsPacket();
@ -36,5 +37,6 @@ signals:
void finished();
};
typedef QSharedPointer<ThreadedAssignment> SharedAssignmentPointer;
#endif /* defined(__hifi__ThreadedAssignment__) */

View file

@ -1594,7 +1594,7 @@ void QTimeSpan::setFromMonths(qreal months)
{
Q_ASSERT_X(hasValidReference(), "setFromMonths", "Can not set interval from time unit month if there is no reference date.");
int fullMonths = int(months);
int fullMonths = (int)months;
qreal fractionalMonth = months - fullMonths;
QDateTime endDate = d->reference;
@ -1631,7 +1631,7 @@ void QTimeSpan::setFromYears(qreal years)
{
Q_ASSERT_X(hasValidReference(), "setFromYears", "Can not set interval from time unit year if there is no reference date.");
int fullYears = int(years);
int fullYears = (int)years;
qreal fractionalYear = years - fullYears;
QDateTime endDate = d->reference;

View file

@ -192,7 +192,7 @@ void ShapeColliderTests::sphereMissesCapsule() {
float delta = 1.3f * (totalRadius + halfHeightB) / (numberOfSteps - 1);
for (int i = 0; i < numberOfSteps; ++i) {
// translate sphereA into world-frame
glm::vec3 localPosition = localStartPosition + (float(i) * delta) * yAxis;
glm::vec3 localPosition = localStartPosition + ((float)i * delta) * yAxis;
sphereA.setPosition(rotation * localPosition + translation);
// sphereA agains capsuleB