This commit is contained in:
Stephen Birarda 2014-07-03 09:25:03 -07:00
commit f1e2ba1267
66 changed files with 1561 additions and 308 deletions

View file

@ -12,6 +12,9 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
# setup for find modules
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../cmake/modules/")
find_package(Qt5 COMPONENTS Script)
include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
# set up the external glm library
include("${MACRO_DIR}/IncludeGLM.cmake")
include_glm(${TARGET_NAME} "${ROOT_DIR}")
@ -35,4 +38,4 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
endif ()

View file

@ -13,13 +13,13 @@
#include <QtCore/QEventLoop>
#include <QtCore/QStandardPaths>
#include <QtCore/QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkDiskCache>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <AudioRingBuffer.h>
#include <AvatarData.h>
#include <NetworkAccessManager.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <ResourceCache.h>
@ -208,12 +208,14 @@ void Agent::run() {
scriptURL = QUrl(_payload);
}
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
QNetworkReply *reply = networkManager->get(QNetworkRequest(scriptURL));
QNetworkDiskCache* cache = new QNetworkDiskCache(networkManager);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply *reply = networkAccessManager.get(QNetworkRequest(scriptURL));
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "agentCache");
networkManager->setCache(cache);
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
Qt::BlockingQueuedConnection,
Q_ARG(QAbstractNetworkCache*, cache));
qDebug() << "Downloading script at" << scriptURL.toString();
@ -222,10 +224,6 @@ void Agent::run() {
loop.exec();
// let the AvatarData and ResourceCache classes use our QNetworkAccessManager
AvatarData::setNetworkAccessManager(networkManager);
ResourceCache::setNetworkAccessManager(networkManager);
QString scriptContents(reply->readAll());
qDebug() << "Downloaded script:" << scriptContents;

View file

@ -38,11 +38,11 @@
#include <QtCore/QJsonObject>
#include <QtCore/QJsonValue>
#include <QtCore/QTimer>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <Logging.h>
#include <NetworkAccessManager.h>
#include <NodeList.h>
#include <Node.h>
#include <PacketHeaders.h>
@ -482,8 +482,8 @@ void AudioMixer::run() {
nodeList->linkedDataCreateCallback = attachNewBufferToNode;
// setup a QNetworkAccessManager to ask the domain-server for our settings
QNetworkAccessManager *networkManager = new QNetworkAccessManager(this);
// setup a NetworkAccessManager to ask the domain-server for our settings
NetworkAccessManager& networkManager = NetworkAccessManager::getInstance();
QUrl settingsJSONURL;
settingsJSONURL.setScheme("http");
@ -500,7 +500,7 @@ void AudioMixer::run() {
qDebug() << "Requesting settings for assignment from domain-server at" << settingsJSONURL.toString();
while (!reply || reply->error() != QNetworkReply::NoError) {
reply = networkManager->get(QNetworkRequest(settingsJSONURL));
reply = networkManager.get(QNetworkRequest(settingsJSONURL));
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));

View file

@ -10,7 +10,6 @@
//
#include <QJsonObject>
#include <QNetworkAccessManager>
#include <QTimer>
#include <QUuid>

View file

@ -51,8 +51,6 @@ DomainServer::DomainServer(int argc, char* argv[]) :
_argumentVariantMap = HifiConfigVariantMap::mergeCLParametersWithJSONConfig(arguments());
_networkAccessManager = new QNetworkAccessManager(this);
if (optionallyReadX509KeyAndCertificate() && optionallySetupOAuth() && optionallySetupAssignmentPayment()) {
// we either read a certificate and private key or were not passed one
// and completed login or did not need to
@ -1196,7 +1194,7 @@ bool DomainServer::handleHTTPSRequest(HTTPSConnection* connection, const QUrl &u
QNetworkRequest tokenRequest(tokenRequestUrl);
tokenRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* tokenReply = _networkAccessManager->post(tokenRequest, tokenPostBody.toLocal8Bit());
QNetworkReply* tokenReply = NetworkAccessManager::getInstance().post(tokenRequest, tokenPostBody.toLocal8Bit());
qDebug() << "Requesting a token for user with session UUID" << uuidStringWithoutCurlyBraces(stateUUID);
@ -1233,7 +1231,7 @@ void DomainServer::handleTokenRequestFinished() {
profileURL.setPath("/api/v1/users/profile");
profileURL.setQuery(QString("%1=%2").arg(OAUTH_JSON_ACCESS_TOKEN_KEY, accessToken));
QNetworkReply* profileReply = _networkAccessManager->get(QNetworkRequest(profileURL));
QNetworkReply* profileReply = NetworkAccessManager::getInstance().get(QNetworkRequest(profileURL));
qDebug() << "Requesting access token for user with session UUID" << uuidStringWithoutCurlyBraces(matchingSessionUUID);

View file

@ -103,8 +103,6 @@ private:
bool _isUsingDTLS;
QNetworkAccessManager* _networkAccessManager;
QUrl _oauthProviderURL;
QString _oauthClientID;
QString _oauthClientSecret;

View file

@ -10,4 +10,7 @@ You can download the Oculus SDK from https://developer.oculusvr.com/ (account cr
You may optionally choose to copy the SDK folders to a location outside the repository (so you can re-use with different checkouts and different projects).
If so our CMake find module expects you to set the ENV variable 'HIFI_LIB_DIR' to a directory containing a subfolder 'oculus' that contains the three folders mentioned above.
2. Clear your build directory, run cmake and build, and you should be all set.
NOTE: For Windows users, you should copy libovr.lib and libovrd.lib from the \oculus\Lib\Win32\VS2010 directory to the \oculus\Lib\Win32\ directory.
2. Clear your build directory, run cmake and build, and you should be all set.

View file

@ -11,18 +11,114 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// the texture containing our permutations and normals
uniform sampler2D permutationNormalTexture;
// implementation based on Ken Perlin's Improved Noise reference implementation (orig. in Java) at
// http://mrl.nyu.edu/~perlin/noise/
uniform sampler2D permutationTexture;
// the noise frequency
const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
const float frequency = 256.0;
//const float frequency = 65536.0; // looks better with current TREE_SCALE, was 1024 when TREE_SCALE was either 512 or 128
// the noise amplitude
const float amplitude = 0.1;
const float amplitude = 0.5;
// the position in model space
varying vec3 position;
// gradient based on gradients from cube edge centers rather than random from texture lookup
float randomEdgeGrad(int hash, vec3 position){
int h = int(mod(hash, 16));
float u = h < 8 ? position.x : position.y;
float v = h < 4 ? position.y : h == 12 || h == 14 ? position.x : position.z;
bool even = mod(hash, 2) == 0;
bool four = mod(hash, 4) == 0;
return (even ? u : -u) + (four ? v : -v);
}
// still have the option to lookup based on texture
float randomTextureGrad(int hash, vec3 position){
float u = float(hash) / 256.0;
vec3 g = -1 + 2 * texture2D(permutationTexture, vec2(u, 0.75)).rgb;
return dot(position, g);
}
float improvedGrad(int hash, vec3 position){
// Untested whether texture lookup is faster than math, uncomment one line or the other to try out
// cube edge gradients versus random spherical gradients sent in texture.
// return randomTextureGrad(hash, position);
return randomEdgeGrad(hash, position);
}
// 5th order fade function to remove 2nd order discontinuties
vec3 fade3(vec3 t){
return t * t * t * (t * (t * 6 - 15) + 10);
}
int permutation(int index){
float u = float(index) / 256.0;
float t = texture2D(permutationTexture, vec2(u, 0.25)).r;
return int(t * 256);
}
float improvedNoise(vec3 position){
int X = int(mod(floor(position.x), 256));
int Y = int(mod(floor(position.y), 256));
int Z = int(mod(floor(position.z), 256));
vec3 fracs = fract(position);
vec3 fades = fade3(fracs);
int A = permutation(X + 0) + Y;
int AA = permutation(A + 0) + Z;
int AB = permutation(A + 1) + Z;
int B = permutation(X + 1) + Y;
int BA = permutation(B + 0) + Z;
int BB = permutation(B + 1) + Z;
float gradAA0 = improvedGrad(permutation(AA + 0), vec3(fracs.x , fracs.y , fracs.z ));
float gradBA0 = improvedGrad(permutation(BA + 0), vec3(fracs.x - 1, fracs.y , fracs.z ));
float gradAB0 = improvedGrad(permutation(AB + 0), vec3(fracs.x , fracs.y - 1, fracs.z ));
float gradBB0 = improvedGrad(permutation(BB + 0), vec3(fracs.x - 1, fracs.y - 1, fracs.z ));
float gradAA1 = improvedGrad(permutation(AA + 1), vec3(fracs.x , fracs.y , fracs.z - 1));
float gradBA1 = improvedGrad(permutation(BA + 1), vec3(fracs.x - 1, fracs.y , fracs.z - 1));
float gradAB1 = improvedGrad(permutation(AB + 1), vec3(fracs.x , fracs.y - 1, fracs.z - 1));
float gradBB1 = improvedGrad(permutation(BB + 1), vec3(fracs.x - 1, fracs.y - 1, fracs.z - 1));
return mix(mix(mix(gradAA0, gradBA0, fades.x), mix(gradAB0, gradBB0, fades.x), fades.y), mix(mix(gradAA1, gradBA1, fades.x), mix(gradAB1, gradBB1, fades.x), fades.y), fades.z);
}
float turbulence(vec3 position, float power){
return (1.0f / power) * improvedNoise(power * position);
}
float turb(vec3 position){
return turbulence(position, 1)
+ turbulence(position, 2),
+ turbulence(position, 4)
+ turbulence(position, 8)
+ turbulence(position, 16)
+ turbulence(position, 32)
+ turbulence(position, 64)
+ turbulence(position, 128)
;
}
void main(void) {
// get noise in range 0 .. 1
float noise = clamp(0.5f + amplitude * turb(position * frequency), 0, 1);
// apply vertex lighting
vec3 color = gl_Color.rgb * vec3(noise, noise, noise);
gl_FragColor = vec4(color, 1);
}
/* old implementation
// returns the gradient at a single corner of our sampling cube
vec3 grad(vec3 location) {
float p1 = texture2D(permutationNormalTexture, vec2(location.x / 256.0, 0.25)).r;
@ -60,7 +156,4 @@ float perlin(vec3 location) {
mix(mix(ffcv, cfcv, params.x), mix(fccv, cccv, params.x), params.y),
params.z);
}
void main(void) {
gl_FragColor = vec4(gl_Color.rgb * (1.0 + amplitude*(perlin(position * frequency) - 1.0)), 1.0);
}
*/

View file

@ -32,7 +32,6 @@
#include <QKeyEvent>
#include <QMenuBar>
#include <QMouseEvent>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkDiskCache>
#include <QOpenGLFramebufferObject>
@ -53,17 +52,18 @@
#include <AccountManager.h>
#include <AudioInjector.h>
#include <LocalVoxelsList.h>
#include <Logging.h>
#include <ModelsScriptingInterface.h>
#include <NetworkAccessManager.h>
#include <OctalCode.h>
#include <OctreeSceneStats.h>
#include <PacketHeaders.h>
#include <ParticlesScriptingInterface.h>
#include <PerfStat.h>
#include <ResourceCache.h>
#include <UserActivityLogger.h>
#include <UUID.h>
#include <OctreeSceneStats.h>
#include <LocalVoxelsList.h>
#include "Application.h"
#include "InterfaceVersion.h"
@ -315,12 +315,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
QString cachePath = QStandardPaths::writableLocation(QStandardPaths::DataLocation);
_networkAccessManager = new QNetworkAccessManager(this);
QNetworkDiskCache* cache = new QNetworkDiskCache(_networkAccessManager);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkDiskCache* cache = new QNetworkDiskCache(&networkAccessManager);
cache->setCacheDirectory(!cachePath.isEmpty() ? cachePath : "interfaceCache");
_networkAccessManager->setCache(cache);
QMetaObject::invokeMethod(&networkAccessManager, "setCache",
Qt::BlockingQueuedConnection,
Q_ARG(QAbstractNetworkCache*, cache));
ResourceCache::setNetworkAccessManager(_networkAccessManager);
ResourceCache::setRequestLimit(3);
_window->setCentralWidget(_glWidget);
@ -403,18 +404,19 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) :
}
Application::~Application() {
qInstallMessageHandler(NULL);
saveSettings();
storeSizeAndPosition();
saveScripts();
int DELAY_TIME = 1000;
UserActivityLogger::getInstance().close(DELAY_TIME);
qInstallMessageHandler(NULL);
// make sure we don't call the idle timer any more
delete idleTimer;
_sharedVoxelSystem.changeTree(new VoxelTree);
saveSettings();
delete _voxelImporter;
// let the avatar mixer know we're out
@ -437,8 +439,6 @@ Application::~Application() {
_particleEditSender.terminate();
_modelEditSender.terminate();
storeSizeAndPosition();
saveScripts();
VoxelTreeElement::removeDeleteHook(&_voxels); // we don't need to do this processing on shutdown
Menu::getInstance()->deleteLater();
@ -446,8 +446,6 @@ Application::~Application() {
_myAvatar = NULL;
delete _glWidget;
AccountManager::getInstance().destroy();
}
void Application::saveSettings() {
@ -595,13 +593,17 @@ void Application::paintGL() {
//Note, the camera distance is set in Camera::setMode() so we dont have to do it here.
_myCamera.setTightness(0.0f); // Camera is directly connected to head without smoothing
_myCamera.setTargetPosition(_myAvatar->getUprightHeadPosition());
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation());
if (OculusManager::isConnected()) {
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation());
} else {
_myCamera.setTargetRotation(_myAvatar->getHead()->getOrientation());
}
} else if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
_myCamera.setTightness(0.0f);
_myCamera.setDistance(MIRROR_FULLSCREEN_DISTANCE * _scaleMirror);
_myCamera.setTargetRotation(_myAvatar->getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PI + _rotateMirror, 0.0f)));
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition());
_myCamera.setTargetPosition(_myAvatar->getHead()->calculateAverageEyePosition() + glm::vec3(0, _raiseMirror * _myAvatar->getScale(), 0));
}
// Update camera position
@ -639,6 +641,10 @@ void Application::paintGL() {
//If we aren't using the glow shader, we have to clear the color and depth buffer
if (!glowEnabled) {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
} else if (OculusManager::isConnected()) {
//Clear the color buffer to ensure that there isnt any residual color
//Left over from when OR was not connected.
glClear(GL_COLOR_BUFFER_BIT);
}
if (OculusManager::isConnected()) {
@ -650,13 +656,8 @@ void Application::paintGL() {
}
} else if (TV3DManager::isConnected()) {
if (glowEnabled) {
_glowEffect.prepare();
}
TV3DManager::display(whichCamera);
if (glowEnabled) {
_glowEffect.render();
}
} else {
if (glowEnabled) {
@ -1144,7 +1145,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) {
_lastMouseMove = usecTimestampNow();
if (_mouseHidden && showMouse && !OculusManager::isConnected()) {
if (_mouseHidden && showMouse && !OculusManager::isConnected() && !TV3DManager::isConnected()) {
getGLWidget()->setCursor(Qt::ArrowCursor);
_mouseHidden = false;
_seenMouseMove = true;
@ -3808,7 +3809,8 @@ void Application::initAvatarAndViewFrustum() {
void Application::checkVersion() {
QNetworkRequest latestVersionRequest((QUrl(CHECK_VERSION_URL)));
latestVersionRequest.setAttribute(QNetworkRequest::CacheLoadControlAttribute, QNetworkRequest::PreferCache);
connect(Application::getInstance()->getNetworkAccessManager()->get(latestVersionRequest), SIGNAL(finished()), SLOT(parseVersionXml()));
QNetworkReply* reply = NetworkAccessManager::getInstance().get(latestVersionRequest);
connect(reply, SIGNAL(finished()), SLOT(parseVersionXml()));
}
void Application::parseVersionXml() {

View file

@ -97,7 +97,6 @@ class QActionGroup;
class QGLWidget;
class QKeyEvent;
class QMouseEvent;
class QNetworkAccessManager;
class QSettings;
class QWheelEvent;
@ -236,7 +235,6 @@ public:
void lockOctreeSceneStats() { _octreeSceneStatsLock.lockForRead(); }
void unlockOctreeSceneStats() { _octreeSceneStatsLock.unlock(); }
QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
GeometryCache* getGeometryCache() { return &_geometryCache; }
AnimationCache* getAnimationCache() { return &_animationCache; }
TextureCache* getTextureCache() { return &_textureCache; }
@ -423,7 +421,6 @@ private:
QThread* _nodeThread;
DatagramProcessor _datagramProcessor;
QNetworkAccessManager* _networkAccessManager;
QMutex _settingsMutex;
QSettings* _settings;
int _numChangedSettings;

View file

@ -432,7 +432,7 @@ void Audio::handleAudioInput() {
float inputToNetworkInputRatio = calculateDeviceToNetworkInputRatio(_numInputCallbackBytes);
unsigned int inputSamplesRequired = NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio;
int inputSamplesRequired = (int)((float)NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL * inputToNetworkInputRatio);
QByteArray inputByteArray = _inputDevice->readAll();
@ -1379,8 +1379,10 @@ bool Audio::switchInputToAudioDevice(const QAudioDeviceInfo& inputDeviceInfo) {
// cleanup any previously initialized device
if (_audioInput) {
// The call to stop() causes _inputDevice to be destructed.
// That in turn causes it to be disconnected (see for example
// http://stackoverflow.com/questions/9264750/qt-signals-and-slots-object-disconnect).
_audioInput->stop();
disconnect(_inputDevice);
_inputDevice = NULL;
delete _audioInput;

View file

@ -91,6 +91,7 @@ Menu::Menu() :
_jsConsole(NULL),
_octreeStatsDialog(NULL),
_lodToolsDialog(NULL),
_userLocationsDialog(NULL),
_maxVoxels(DEFAULT_MAX_VOXELS_PER_SYSTEM),
_voxelSizeScale(DEFAULT_OCTREE_SIZE_SCALE),
_oculusUIAngularSize(DEFAULT_OCULUS_UI_ANGULAR_SIZE),
@ -166,6 +167,11 @@ Menu::Menu() :
Qt::CTRL | Qt::Key_N,
this,
SLOT(nameLocation()));
addActionToQMenuAndActionHash(fileMenu,
MenuOption::MyLocations,
Qt::CTRL | Qt::Key_K,
this,
SLOT(toggleLocationList()));
addActionToQMenuAndActionHash(fileMenu,
MenuOption::GoTo,
Qt::Key_At,
@ -1184,6 +1190,17 @@ void Menu::namedLocationCreated(LocationManager::NamedLocationCreateResponse res
msgBox.exec();
}
void Menu::toggleLocationList() {
if (!_userLocationsDialog) {
_userLocationsDialog = new UserLocationsDialog(Application::getInstance()->getWindow());
}
if (_userLocationsDialog->isVisible()) {
_userLocationsDialog->hide();
} else {
_userLocationsDialog->show();
}
}
void Menu::nameLocation() {
// check if user is logged in or show login dialog if not

View file

@ -29,6 +29,7 @@
#include "ui/JSConsole.h"
#include "ui/LoginDialog.h"
#include "ui/ScriptEditorWindow.h"
#include "ui/UserLocationsDialog.h"
const float ADJUST_LOD_DOWN_FPS = 40.0;
const float ADJUST_LOD_UP_FPS = 55.0;
@ -199,6 +200,7 @@ private slots:
void goToDomainDialog();
void goToLocation();
void nameLocation();
void toggleLocationList();
void bandwidthDetailsClosed();
void octreeStatsDetailsClosed();
void lodToolsClosed();
@ -265,6 +267,7 @@ private:
QDialog* _jsConsole;
OctreeStatsDialog* _octreeStatsDialog;
LodToolsDialog* _lodToolsDialog;
UserLocationsDialog* _userLocationsDialog;
int _maxVoxels;
float _voxelSizeScale;
float _oculusUIAngularSize;
@ -395,6 +398,7 @@ namespace MenuOption {
const QString MoveWithLean = "Move with Lean";
const QString MuteAudio = "Mute Microphone";
const QString MuteEnvironment = "Mute Environment";
const QString MyLocations = "My Locations...";
const QString NameLocation = "Name this location";
const QString NewVoxelCullingMode = "New Voxel Culling Mode";
const QString OctreeStats = "Voxel and Particle Statistics";

View file

@ -396,7 +396,7 @@ void ModelUploader::uploadFailed(QNetworkReply::NetworkError errorCode, const QS
void ModelUploader::checkS3() {
qDebug() << "Checking S3 for " << _url;
QNetworkRequest request(_url);
QNetworkReply* reply = _networkAccessManager.head(request);
QNetworkReply* reply = NetworkAccessManager::getInstance().head(request);
connect(reply, SIGNAL(finished()), SLOT(processCheck()));
}

View file

@ -58,7 +58,6 @@ private:
bool _readyToSend;
QHttpMultiPart* _dataMultiPart;
QNetworkAccessManager _networkAccessManager;
int _numberOfChecks;
QTimer _timer;

View file

@ -11,14 +11,15 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QNetworkAccessManager>
#include <QUrl>
#include <QUrlQuery>
#include <QXmlStreamReader>
#include "ScriptsModel.h"
#include <NetworkAccessManager.h>
#include "Menu.h"
#include "ScriptsModel.h"
static const QString S3_URL = "http://highfidelity-public.s3-us-west-1.amazonaws.com";
static const QString PUBLIC_URL = "http://public.highfidelity.io";
@ -30,8 +31,6 @@ static const QString IS_TRUNCATED_NAME = "IsTruncated";
static const QString CONTAINER_NAME = "Contents";
static const QString KEY_NAME = "Key";
static const int SCRIPT_PATH = Qt::UserRole;
ScriptItem::ScriptItem(const QString& filename, const QString& fullPath) :
_filename(filename),
_fullPath(fullPath) {
@ -113,14 +112,15 @@ void ScriptsModel::requestRemoteFiles(QString marker) {
}
url.setQuery(query);
QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
accessManager->get(request);
QNetworkReply* reply = networkAccessManager.get(request);
connect(reply, SIGNAL(finished()), SLOT(downloadFinished()));
}
void ScriptsModel::downloadFinished(QNetworkReply* reply) {
void ScriptsModel::downloadFinished() {
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
bool finished = true;
if (reply->error() == QNetworkReply::NoError) {

View file

@ -43,7 +43,7 @@ public:
protected slots:
void updateScriptsLocation(const QString& newPath);
void downloadFinished(QNetworkReply* reply);
void downloadFinished();
void reloadLocalFiles();
void reloadRemoteFiles();

View file

@ -0,0 +1,246 @@
//
// UserLocationsModel.cpp
// interface/src
//
// Created by Ryan Huffman on 06/24/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QDebug>
#include <QJsonArray>
#include <QJsonDocument>
#include <QMessageBox>
#include "AccountManager.h"
#include "Application.h"
#include "UserLocationsModel.h"
static const QString PLACES_GET = "/api/v1/places";
static const QString PLACES_UPDATE = "/api/v1/places/%1";
static const QString PLACES_DELETE= "/api/v1/places/%1";
UserLocation::UserLocation(QString id, QString name, QString location) :
_id(id),
_name(name),
_location(location),
_previousName(name),
_updating(false) {
}
void UserLocation::requestRename(const QString& newName) {
if (!_updating && newName.toLower() != _name) {
_updating = true;
JSONCallbackParameters callbackParams(this, "handleRenameResponse", this, "handleRenameError");
QJsonObject jsonNameObject;
jsonNameObject.insert("name", QJsonValue(newName));
QJsonDocument jsonDocument(jsonNameObject);
AccountManager::getInstance().authenticatedRequest(PLACES_UPDATE.arg(_id),
QNetworkAccessManager::PutOperation,
callbackParams,
jsonDocument.toJson());
_previousName = _name;
_name = newName;
emit updated(_name);
}
}
void UserLocation::handleRenameResponse(const QJsonObject& responseData) {
_updating = false;
QJsonValue status = responseData["status"];
if (!status.isUndefined() && status.toString() == "success") {
QString updatedName = responseData["data"].toObject()["name"].toString();
_name = updatedName;
} else {
_name = _previousName;
QString msg = "There was an error renaming location '" + _name + "'";
QJsonValue data = responseData["data"];
if (!data.isUndefined()) {
QJsonValue nameError = data.toObject()["name"];
if (!nameError.isUndefined()) {
msg += ": " + nameError.toString();
}
}
qDebug() << msg;
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
}
emit updated(_name);
}
void UserLocation::handleRenameError(QNetworkReply::NetworkError error, const QString& errorString) {
_updating = false;
QString msg = "There was an error renaming location '" + _name + "': " + errorString;
qDebug() << msg;
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
emit updated(_name);
}
void UserLocation::requestDelete() {
if (!_updating) {
_updating = true;
JSONCallbackParameters callbackParams(this, "handleDeleteResponse", this, "handleDeleteError");
AccountManager::getInstance().authenticatedRequest(PLACES_DELETE.arg(_id),
QNetworkAccessManager::DeleteOperation,
callbackParams);
}
}
void UserLocation::handleDeleteResponse(const QJsonObject& responseData) {
_updating = false;
QJsonValue status = responseData["status"];
if (!status.isUndefined() && status.toString() == "success") {
emit deleted(_name);
} else {
QString msg = "There was an error deleting location '" + _name + "'";
qDebug() << msg;
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
}
}
void UserLocation::handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString) {
_updating = false;
QString msg = "There was an error deleting location '" + _name + "': " + errorString;
qDebug() << msg;
QMessageBox::warning(Application::getInstance()->getWindow(), "Error", msg);
}
UserLocationsModel::UserLocationsModel(QObject* parent) :
QAbstractListModel(parent),
_updating(false) {
refresh();
}
UserLocationsModel::~UserLocationsModel() {
qDeleteAll(_locations);
_locations.clear();
}
void UserLocationsModel::update() {
beginResetModel();
endResetModel();
}
void UserLocationsModel::deleteLocation(const QModelIndex& index) {
UserLocation* location = _locations[index.row()];
location->requestDelete();
}
void UserLocationsModel::renameLocation(const QModelIndex& index, const QString& newName) {
UserLocation* location = _locations[index.row()];
location->requestRename(newName);
}
void UserLocationsModel::refresh() {
if (!_updating) {
beginResetModel();
qDeleteAll(_locations);
_locations.clear();
_updating = true;
endResetModel();
JSONCallbackParameters callbackParams(this, "handleLocationsResponse");
AccountManager::getInstance().authenticatedRequest(PLACES_GET,
QNetworkAccessManager::GetOperation,
callbackParams);
}
}
void UserLocationsModel::handleLocationsResponse(const QJsonObject& responseData) {
_updating = false;
QJsonValue status = responseData["status"];
if (!status.isUndefined() && status.toString() == "success") {
beginResetModel();
QJsonArray locations = responseData["data"].toObject()["places"].toArray();
for (QJsonArray::const_iterator it = locations.constBegin(); it != locations.constEnd(); it++) {
QJsonObject location = (*it).toObject();
QJsonObject address = location["address"].toObject();
UserLocation* userLocation = new UserLocation(location["id"].toString(), location["name"].toString(),
"hifi://" + address["domain"].toString()
+ "/" + address["position"].toString()
+ "/" + address["orientation"].toString());
_locations.append(userLocation);
connect(userLocation, &UserLocation::deleted, this, &UserLocationsModel::removeLocation);
connect(userLocation, &UserLocation::updated, this, &UserLocationsModel::update);
}
endResetModel();
} else {
qDebug() << "Error loading location data";
}
}
void UserLocationsModel::removeLocation(const QString& name) {
beginResetModel();
for (QList<UserLocation*>::iterator it = _locations.begin(); it != _locations.end(); it++) {
if ((*it)->name() == name) {
_locations.erase(it);
break;
}
}
endResetModel();
}
int UserLocationsModel::rowCount(const QModelIndex& parent) const {
if (parent.isValid()) {
return 0;
}
if (_updating) {
return 1;
}
return _locations.length();
}
QVariant UserLocationsModel::data(const QModelIndex& index, int role) const {
if (role == Qt::DisplayRole) {
if (_updating) {
return QVariant("Updating...");
} else if (index.row() > _locations.length()) {
return QVariant();
} else if (index.column() == NameColumn) {
return _locations[index.row()]->name();
} else if (index.column() == LocationColumn) {
return QVariant(_locations[index.row()]->location());
}
}
return QVariant();
}
QVariant UserLocationsModel::headerData(int section, Qt::Orientation orientation, int role) const {
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (section) {
case NameColumn: return "Name";
case LocationColumn: return "Location";
default: return QVariant();
}
}
return QVariant();
}
Qt::ItemFlags UserLocationsModel::flags(const QModelIndex& index) const {
if (index.row() < _locations.length()) {
UserLocation* ul = _locations[index.row()];
if (ul->isUpdating()) {
return Qt::NoItemFlags;
}
}
return QAbstractListModel::flags(index);
}

View file

@ -0,0 +1,82 @@
//
// UserLocationsModel.h
// interface/src
//
// Created by Ryan Huffman on 06/24/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_UserLocationsModel_h
#define hifi_UserLocationsModel_h
#include <QAbstractListModel>
#include <QModelIndex>
#include <QVariant>
class UserLocation : public QObject {
Q_OBJECT
public:
UserLocation(QString id, QString name, QString location);
bool isUpdating() { return _updating; }
void requestRename(const QString& newName);
void requestDelete();
QString id() { return _id; }
QString name() { return _name; }
QString location() { return _location; }
public slots:
void handleRenameResponse(const QJsonObject& responseData);
void handleRenameError(QNetworkReply::NetworkError error, const QString& errorString);
void handleDeleteResponse(const QJsonObject& responseData);
void handleDeleteError(QNetworkReply::NetworkError error, const QString& errorString);
signals:
void updated(const QString& name);
void deleted(const QString& name);
private:
QString _id;
QString _name;
QString _location;
QString _previousName;
bool _updating;
};
class UserLocationsModel : public QAbstractListModel {
Q_OBJECT
public:
UserLocationsModel(QObject* parent = NULL);
~UserLocationsModel();
virtual int rowCount(const QModelIndex& parent = QModelIndex()) const;
virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
virtual int columnCount(const QModelIndex& parent = QModelIndex()) const { return 2; };
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual Qt::ItemFlags flags(const QModelIndex& index) const;
void deleteLocation(const QModelIndex& index);
void renameLocation(const QModelIndex& index, const QString& newName);
enum Columns {
NameColumn = 0,
LocationColumn
};
public slots:
void refresh();
void update();
void handleLocationsResponse(const QJsonObject& responseData);
void removeLocation(const QString& name);
private:
bool _updating;
QList<UserLocation*> _locations;
};
#endif // hifi_UserLocationsModel_h

View file

@ -51,10 +51,10 @@ void FaceModel::maybeUpdateNeckRotation(const JointState& parentState, const FBX
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
joint.preTransform * glm::mat4_cast(joint.preRotation)));
state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningHead->getFinalRoll(), glm::normalize(inverse * axes[2]))
state.setRotationInParentFrame(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;
* joint.rotation);
}
void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
@ -68,8 +68,8 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
_owningHead->getSaccade() - _translation, 1.0f));
glm::quat between = rotationBetween(front, lookAt);
const float MAX_ANGLE = 30.0f * RADIANS_PER_DEGREE;
state._rotationInParentFrame = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
joint.rotation;
state.setRotationInParentFrame(glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
joint.rotation);
}
void FaceModel::updateJointState(int index) {

View file

@ -219,10 +219,9 @@ void SkeletonModel::applyPalmData(int jointIndex, PalmData& palm) {
JointState& parentState = _jointStates[parentJointIndex];
parentState.setRotationFromBindFrame(palmRotation, PALM_PRIORITY);
// lock hand to forearm by slamming its rotation (in parent-frame) to identity
_jointStates[jointIndex]._rotationInParentFrame = glm::quat();
_jointStates[jointIndex].setRotationInParentFrame(glm::quat());
} else {
setJointPosition(jointIndex, palmPosition, palmRotation,
true, -1, false, glm::vec3(0.0f, -1.0f, 0.0f), PALM_PRIORITY);
inverseKinematics(jointIndex, palmPosition, palmRotation, PALM_PRIORITY);
}
}
@ -258,9 +257,9 @@ void SkeletonModel::maybeUpdateLeanRotation(const JointState& parentState, const
glm::mat3 axes = glm::mat3_cast(glm::quat());
glm::mat3 inverse = glm::mat3(glm::inverse(parentState.getTransform() * glm::translate(state.getDefaultTranslationInParentFrame()) *
joint.preTransform * glm::mat4_cast(joint.preRotation * joint.rotation)));
state._rotationInParentFrame = glm::angleAxis(- RADIANS_PER_DEGREE * _owningAvatar->getHead()->getFinalLeanSideways(),
state.setRotationInParentFrame(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;
glm::normalize(inverse * axes[0])) * joint.rotation);
}
void SkeletonModel::maybeUpdateNeckRotation(const JointState& parentState, const FBXJoint& joint, JointState& state) {
@ -537,6 +536,11 @@ void SkeletonModel::buildRagdollConstraints() {
}
}
void SkeletonModel::updateVisibleJointStates() {
Model::updateVisibleJointStates();
// TODO: implement this to move visible joints to agree with joint shape positions
}
// virtual
void SkeletonModel::stepRagdollForward(float deltaTime) {
const float RAGDOLL_FOLLOWS_JOINTS_TIMESCALE = 0.03f;
@ -644,7 +648,6 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
_ragdollPoints[i]._lastPosition = _ragdollPoints[i]._position;
continue;
}
assert(parentIndex != -1);
glm::quat modifiedRotation = joint.preRotation * joint.rotation * joint.postRotation;
transforms[i] = transforms[parentIndex] * glm::translate(joint.translation)
@ -700,7 +703,7 @@ void SkeletonModel::computeBoundingShape(const FBXGeometry& geometry) {
_boundingRadius = 0.5f * glm::length(diagonal);
}
void SkeletonModel::resetShapePositions() {
void SkeletonModel::resetShapePositionsToDefaultPose() {
// DEBUG method.
// Moves shapes to the joint default locations for debug visibility into
// how the bounding shape is computed.

View file

@ -93,6 +93,8 @@ public:
/// Retrieve the positions of up to two eye meshes.
/// \return whether or not both eye meshes were found
bool getEyePositions(glm::vec3& firstEyePosition, glm::vec3& secondEyePosition) const;
virtual void updateVisibleJointStates();
// virtual overrride from Ragdoll
virtual void stepRagdollForward(float deltaTime);
@ -104,7 +106,7 @@ public:
float getBoundingShapeRadius() const { return _boundingShape.getRadius(); }
const CapsuleShape& getBoundingShape() const { return _boundingShape; }
void resetShapePositions(); // DEBUG method
void resetShapePositionsToDefaultPose(); // DEBUG method
void renderRagdoll();
protected:

View file

@ -266,7 +266,7 @@ void OculusManager::display(const glm::quat &bodyOrientation, const glm::vec3 &p
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
// We only need to render the overlays to a texture once, then we just render the texture as a quad
// We only need to render the overlays to a texture once, then we just render the texture on the hemisphere
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
applicationOverlay.renderOverlay(true);
const bool displayOverlays = Menu::getInstance()->isOptionChecked(MenuOption::DisplayOculusOverlays);

View file

@ -93,6 +93,18 @@ void TV3DManager::display(Camera& whichCamera) {
int portalW = Application::getInstance()->getGLWidget()->width() / 2;
int portalH = Application::getInstance()->getGLWidget()->height();
const bool glowEnabled = Menu::getInstance()->isOptionChecked(MenuOption::EnableGlowEffect);
ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
// We only need to render the overlays to a texture once, then we just render the texture as a quad
// PrioVR will only work if renderOverlay is called, calibration is connected to Application::renderingOverlay()
applicationOverlay.renderOverlay(true);
if (glowEnabled) {
Application::getInstance()->getGlowEffect()->prepare();
}
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glEnable(GL_SCISSOR_TEST);
@ -102,13 +114,21 @@ void TV3DManager::display(Camera& whichCamera) {
glPushMatrix();
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // reset projection matrix
glFrustum(_leftEye.left, _leftEye.right, _leftEye.bottom, _leftEye.top, nearZ, farZ); // set left view frustum
GLfloat p[4][4];
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
GLfloat cotangent = p[1][1];
GLfloat fov = atan(1.0f / cotangent);
glTranslatef(_leftEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Application::getInstance()->displaySide(whichCamera);
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
}
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
@ -124,14 +144,25 @@ void TV3DManager::display(Camera& whichCamera) {
glMatrixMode(GL_PROJECTION);
glLoadIdentity(); // reset projection matrix
glFrustum(_rightEye.left, _rightEye.right, _rightEye.bottom, _rightEye.top, nearZ, farZ); // set left view frustum
GLfloat p[4][4];
glGetFloatv(GL_PROJECTION_MATRIX, &(p[0][0]));
GLfloat cotangent = p[1][1];
GLfloat fov = atan(1.0f / cotangent);
glTranslatef(_rightEye.modelTranslation, 0.0, 0.0); // translate to cancel parallax
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
Application::getInstance()->displaySide(whichCamera);
applicationOverlay.displayOverlayTexture3DTV(whichCamera, _aspect, fov);
}
glPopMatrix();
glDisable(GL_SCISSOR_TEST);
// reset the viewport to how we started
glViewport(0, 0, Application::getInstance()->getGLWidget()->width(), Application::getInstance()->getGLWidget()->height());
if (glowEnabled) {
Application::getInstance()->getGlowEffect()->render();
}
}

View file

@ -11,14 +11,26 @@
#include <glm/gtx/norm.hpp>
//#include <GeometryUtil.h>
#include <SharedUtil.h>
#include "JointState.h"
JointState::JointState() :
_animationPriority(0.0f),
_fbxJoint(NULL) {
_fbxJoint(NULL),
_isConstrained(false) {
}
void JointState::copyState(const JointState& state) {
_animationPriority = state._animationPriority;
_transform = state._transform;
_rotation = extractRotation(_transform);
_rotationInParentFrame = state._rotationInParentFrame;
_visibleTransform = state._visibleTransform;
_visibleRotation = extractRotation(_visibleTransform);
_visibleRotationInParentFrame = state._visibleRotationInParentFrame;
// DO NOT copy _fbxJoint
}
void JointState::setFBXJoint(const FBXJoint* joint) {
@ -26,14 +38,10 @@ void JointState::setFBXJoint(const FBXJoint* joint) {
_rotationInParentFrame = joint->rotation;
// NOTE: JointState does not own the FBXJoint to which it points.
_fbxJoint = joint;
}
void JointState::copyState(const JointState& state) {
_rotationInParentFrame = state._rotationInParentFrame;
_transform = state._transform;
_rotation = extractRotation(_transform);
_animationPriority = state._animationPriority;
// DO NOT copy _fbxJoint
// precompute whether there are any constraints or not
float distanceMin = glm::distance(_fbxJoint->rotationMin, glm::vec3(-PI));
float distanceMax = glm::distance(_fbxJoint->rotationMax, glm::vec3(PI));
_isConstrained = distanceMin > EPSILON || distanceMax > EPSILON;
}
void JointState::computeTransform(const glm::mat4& parentTransform) {
@ -43,6 +51,13 @@ void JointState::computeTransform(const glm::mat4& parentTransform) {
_rotation = extractRotation(_transform);
}
void JointState::computeVisibleTransform(const glm::mat4& parentTransform) {
glm::quat modifiedRotation = _fbxJoint->preRotation * _visibleRotationInParentFrame * _fbxJoint->postRotation;
glm::mat4 modifiedTransform = _fbxJoint->preTransform * glm::mat4_cast(modifiedRotation) * _fbxJoint->postTransform;
_visibleTransform = parentTransform * glm::translate(_fbxJoint->translation) * modifiedTransform;
_visibleRotation = extractRotation(_visibleTransform);
}
glm::quat JointState::getRotationFromBindToModelFrame() const {
return _rotation * _fbxJoint->inverseBindRotation;
}
@ -50,16 +65,16 @@ glm::quat JointState::getRotationFromBindToModelFrame() const {
void JointState::restoreRotation(float fraction, float priority) {
assert(_fbxJoint != NULL);
if (priority == _animationPriority || _animationPriority == 0.0f) {
_rotationInParentFrame = safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction);
setRotationInParentFrame(safeMix(_rotationInParentFrame, _fbxJoint->rotation, fraction));
_animationPriority = 0.0f;
}
}
void JointState::setRotationFromBindFrame(const glm::quat& rotation, float priority) {
// rotation is from bind- to model-frame
assert(_fbxJoint != NULL);
if (priority >= _animationPriority) {
// rotation is from bind- to model-frame
_rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation);
setRotationInParentFrame(_rotationInParentFrame * glm::inverse(_rotation) * rotation * glm::inverse(_fbxJoint->inverseBindRotation));
_animationPriority = priority;
}
}
@ -68,6 +83,9 @@ void JointState::clearTransformTranslation() {
_transform[3][0] = 0.0f;
_transform[3][1] = 0.0f;
_transform[3][2] = 0.0f;
_visibleTransform[3][0] = 0.0f;
_visibleTransform[3][1] = 0.0f;
_visibleTransform[3][2] = 0.0f;
}
void JointState::setRotation(const glm::quat& rotation, bool constrain, float priority) {
@ -75,27 +93,59 @@ void JointState::setRotation(const glm::quat& rotation, bool constrain, float pr
}
void JointState::applyRotationDelta(const glm::quat& delta, bool constrain, float priority) {
// NOTE: delta is in jointParent-frame
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
if (priority < _animationPriority) {
return;
}
_animationPriority = priority;
if (!constrain || (_fbxJoint->rotationMin == glm::vec3(-PI, -PI, -PI) &&
_fbxJoint->rotationMax == glm::vec3(PI, PI, PI))) {
if (!constrain || !_isConstrained) {
// no constraints
_rotationInParentFrame = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
_rotation = delta * _rotation;
return;
}
glm::quat targetRotation = delta * _rotation;
glm::vec3 eulers = safeEulerAngles(_rotationInParentFrame * glm::inverse(_rotation) * targetRotation);
glm::quat newRotation = glm::quat(glm::clamp(eulers, _fbxJoint->rotationMin, _fbxJoint->rotationMax));
_rotation = _rotation * glm::inverse(_rotationInParentFrame) * newRotation;
_rotationInParentFrame = newRotation;
glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
setRotationInParentFrame(targetRotation);
}
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
/// This helps keep an IK solution stable.
void JointState::mixRotationDelta(const glm::quat& delta, float mixFactor, float priority) {
// NOTE: delta is in model-frame
assert(_fbxJoint != NULL);
if (priority < _animationPriority) {
return;
}
_animationPriority = priority;
glm::quat targetRotation = _rotationInParentFrame * glm::inverse(_rotation) * delta * _rotation;
if (mixFactor > 0.0f && mixFactor <= 1.0f) {
targetRotation = safeMix(targetRotation, _fbxJoint->rotation, mixFactor);
}
setRotationInParentFrame(targetRotation);
}
glm::quat JointState::computeParentRotation() const {
// R = Rp * Rpre * r * Rpost
// Rp = R * (Rpre * r * Rpost)^
return _rotation * glm::inverse(_fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation);
}
void JointState::setRotationInParentFrame(const glm::quat& targetRotation) {
glm::quat parentRotation = computeParentRotation();
_rotationInParentFrame = targetRotation;
// R' = Rp * Rpre * r' * Rpost
_rotation = parentRotation * _fbxJoint->preRotation * _rotationInParentFrame * _fbxJoint->postRotation;
}
const glm::vec3& JointState::getDefaultTranslationInParentFrame() const {
assert(_fbxJoint != NULL);
return _fbxJoint->translation;
}
void JointState::slaveVisibleTransform() {
_visibleTransform = _transform;
_visibleRotation = _rotation;
_visibleRotationInParentFrame = _rotationInParentFrame;
}

View file

@ -22,12 +22,19 @@ class JointState {
public:
JointState();
void copyState(const JointState& state);
void setFBXJoint(const FBXJoint* joint);
const FBXJoint& getFBXJoint() const { return *_fbxJoint; }
void copyState(const JointState& state);
void computeTransform(const glm::mat4& parentTransform);
void computeVisibleTransform(const glm::mat4& parentTransform);
const glm::mat4& getVisibleTransform() const { return _visibleTransform; }
glm::quat getVisibleRotation() const { return _visibleRotation; }
glm::vec3 getVisiblePosition() const { return extractTranslation(_visibleTransform); }
const glm::mat4& getTransform() const { return _transform; }
glm::quat getRotation() const { return _rotation; }
@ -39,11 +46,19 @@ public:
/// \param rotation rotation of joint in model-frame
void setRotation(const glm::quat& rotation, bool constrain, float priority);
/// \param delta is in the jointParent-frame
/// \param delta is in the model-frame
void applyRotationDelta(const glm::quat& delta, bool constrain = true, float priority = 1.0f);
const glm::vec3& getDefaultTranslationInParentFrame() const;
/// Applies delta rotation to joint but mixes a little bit of the default pose as well.
/// This helps keep an IK solution stable.
/// \param delta rotation change in model-frame
/// \param mixFactor fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
/// \param priority priority level of this animation blend
void mixRotationDelta(const glm::quat& delta, float mixFactor, float priority = 1.0f);
/// Blends a fraciton of default pose into joint rotation.
/// \param fraction fraction in range [0,1] of how much default pose to blend in (0 is none, 1 is all)
/// \param priority priority level of this animation blend
void restoreRotation(float fraction, float priority);
/// \param rotation is from bind- to model-frame
@ -51,16 +66,36 @@ public:
/// NOTE: the JointState's model-frame transform/rotation are NOT updated!
void setRotationFromBindFrame(const glm::quat& rotation, float priority);
void setRotationInParentFrame(const glm::quat& targetRotation);
const glm::quat& getRotationInParentFrame() const { return _rotationInParentFrame; }
const glm::vec3& getDefaultTranslationInParentFrame() const;
void clearTransformTranslation();
glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
void slaveVisibleTransform();
float _animationPriority; // the priority of the animation affecting this joint
private:
/// \return parent model-frame rotation
// (used to keep _rotation consistent when modifying _rotationInWorldFrame directly)
glm::quat computeParentRotation() const;
/// debug helper function
void loadBindRotation();
glm::mat4 _transform; // joint- to model-frame
glm::quat _rotation; // joint- to model-frame
glm::quat _rotationInParentFrame; // joint- to parentJoint-frame
glm::mat4 _visibleTransform;
glm::quat _visibleRotation;
glm::quat _visibleRotationInParentFrame;
const FBXJoint* _fbxJoint; // JointState does NOT own its FBXJoint
bool _isConstrained;
};
#endif // hifi_JointState_h

View file

@ -39,8 +39,8 @@ Model::Model(QObject* parent) :
_scaledToFit(false),
_snapModelToCenter(false),
_snappedToCenter(false),
_showTrueJointTransforms(false),
_rootIndex(-1),
//_enableCollisionShapes(false),
_lodDistance(0.0f),
_pupilDilation(0.0f),
_url("http://invalid.com") {
@ -460,7 +460,7 @@ void Model::reset() {
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i]._rotationInParentFrame = geometry.joints.at(i).rotation;
_jointStates[i].setRotationInParentFrame(geometry.joints.at(i).rotation);
}
}
@ -571,6 +571,9 @@ void Model::setJointStates(QVector<JointState> states) {
radius = distance;
}
}
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].slaveVisibleTransform();
}
_boundingRadius = radius;
}
@ -686,7 +689,7 @@ bool Model::getJointState(int index, glm::quat& rotation) const {
if (index == -1 || index >= _jointStates.size()) {
return false;
}
rotation = _jointStates.at(index)._rotationInParentFrame;
rotation = _jointStates.at(index).getRotationInParentFrame();
const glm::quat& defaultRotation = _geometry->getFBXGeometry().joints.at(index).rotation;
return glm::abs(rotation.x - defaultRotation.x) >= EPSILON ||
glm::abs(rotation.y - defaultRotation.y) >= EPSILON ||
@ -699,7 +702,7 @@ void Model::setJointState(int index, bool valid, const glm::quat& rotation, floa
JointState& state = _jointStates[index];
if (priority >= state._animationPriority) {
if (valid) {
state._rotationInParentFrame = rotation;
state.setRotationInParentFrame(rotation);
state._animationPriority = priority;
} else {
state.restoreRotation(1.0f, priority);
@ -765,6 +768,23 @@ bool Model::getJointCombinedRotation(int jointIndex, glm::quat& rotation) const
return true;
}
bool Model::getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
// position is in world-frame
position = _translation + _rotation * _jointStates[jointIndex].getVisiblePosition();
return true;
}
bool Model::getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const {
if (jointIndex == -1 || jointIndex >= _jointStates.size()) {
return false;
}
rotation = _rotation * _jointStates[jointIndex].getVisibleRotation();
return true;
}
QStringList Model::getJointNames() const {
if (QThread::currentThread() != thread()) {
QStringList result;
@ -918,6 +938,8 @@ void Model::simulateInternal(float deltaTime) {
for (int i = 0; i < _jointStates.size(); i++) {
updateJointState(i);
}
updateVisibleJointStates();
_shapesAreDirty = ! _shapes.isEmpty();
// update the attachment transforms and simulate them
@ -928,8 +950,13 @@ void Model::simulateInternal(float deltaTime) {
glm::vec3 jointTranslation = _translation;
glm::quat jointRotation = _rotation;
getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
getJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
if (_showTrueJointTransforms) {
getJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
getJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
} else {
getVisibleJointPositionInWorldFrame(attachment.jointIndex, jointTranslation);
getVisibleJointRotationInWorldFrame(attachment.jointIndex, jointRotation);
}
model->setTranslation(jointTranslation + jointRotation * attachment.translation * _scale);
model->setRotation(jointRotation * attachment.rotation);
@ -944,9 +971,16 @@ void Model::simulateInternal(float deltaTime) {
for (int i = 0; i < _meshStates.size(); i++) {
MeshState& state = _meshStates[i];
const FBXMesh& mesh = geometry.meshes.at(i);
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
if (_showTrueJointTransforms) {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getTransform() * cluster.inverseBindMatrix;
}
} else {
for (int j = 0; j < mesh.clusters.size(); j++) {
const FBXCluster& cluster = mesh.clusters.at(j);
state.clusterMatrices[j] = modelToWorld * _jointStates[cluster.jointIndex].getVisibleTransform() * cluster.inverseBindMatrix;
}
}
}
@ -972,6 +1006,14 @@ void Model::updateJointState(int index) {
}
}
void Model::updateVisibleJointStates() {
if (!_showTrueJointTransforms) {
for (int i = 0; i < _jointStates.size(); i++) {
_jointStates[i].slaveVisibleTransform();
}
}
}
bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation, bool useRotation,
int lastFreeIndex, bool allIntermediatesFree, const glm::vec3& alignment, float priority) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
@ -1058,6 +1100,128 @@ bool Model::setJointPosition(int jointIndex, const glm::vec3& position, const gl
return true;
}
void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm::quat& targetRotation, float priority) {
// NOTE: targetRotation is from bind- to model-frame
if (endIndex == -1 || _jointStates.isEmpty()) {
return;
}
const FBXGeometry& geometry = _geometry->getFBXGeometry();
const QVector<int>& freeLineage = geometry.joints.at(endIndex).freeLineage;
if (freeLineage.isEmpty()) {
return;
}
int numFree = freeLineage.size();
// store and remember topmost parent transform
glm::mat4 topParentTransform;
{
int index = freeLineage.last();
const JointState& state = _jointStates.at(index);
const FBXJoint& joint = state.getFBXJoint();
int parentIndex = joint.parentIndex;
if (parentIndex == -1) {
const FBXGeometry& geometry = _geometry->getFBXGeometry();
topParentTransform = glm::scale(_scale) * glm::translate(_offset) * geometry.offset;
} else {
topParentTransform = _jointStates[parentIndex].getTransform();
}
}
// this is a cyclic coordinate descent algorithm: see
// http://www.ryanjuckett.com/programming/animation/21-cyclic-coordinate-descent-in-2d
// keep track of the position of the end-effector
JointState& endState = _jointStates[endIndex];
glm::vec3 endPosition = endState.getPosition();
float distanceToGo = glm::distance(targetPosition, endPosition);
const int MAX_ITERATION_COUNT = 2;
const float ACCEPTABLE_IK_ERROR = 0.005f; // 5mm
int numIterations = 0;
do {
++numIterations;
// moving up, rotate each free joint to get endPosition closer to target
for (int j = 1; j < numFree; j++) {
int nextIndex = freeLineage.at(j);
JointState& nextState = _jointStates[nextIndex];
FBXJoint nextJoint = nextState.getFBXJoint();
if (! nextJoint.isFree) {
continue;
}
glm::vec3 pivot = nextState.getPosition();
glm::vec3 leverArm = endPosition - pivot;
float leverLength = glm::length(leverArm);
if (leverLength < EPSILON) {
continue;
}
glm::quat deltaRotation = rotationBetween(leverArm, targetPosition - pivot);
/* DON'T REMOVE! This code provides the gravitational effect on the IK solution.
* It is commented out for the moment because we're blending the IK solution with
* the default pose which provides similar stability, but we might want to use
* gravity again later.
// We want to mix the shortest rotation with one that will pull the system down with gravity.
// So we compute a simplified center of mass, where each joint has a mass of 1.0 and we don't
// bother averaging it because we only need direction.
if (j > 1) {
glm::vec3 centerOfMass(0.0f);
for (int k = 0; k < j; ++k) {
int massIndex = freeLineage.at(k);
centerOfMass += _jointStates[massIndex].getPosition() - pivot;
}
// the gravitational effect is a rotation that tends to align the two cross products
const glm::vec3 worldAlignment = glm::vec3(0.0f, -1.f, 0.0f);
glm::quat gravityDelta = rotationBetween(glm::cross(centerOfMass, leverArm),
glm::cross(worldAlignment, leverArm));
float gravityAngle = glm::angle(gravityDelta);
const float MIN_GRAVITY_ANGLE = 0.1f;
float mixFactor = 0.5f;
if (gravityAngle < MIN_GRAVITY_ANGLE) {
// the final rotation is a mix of the two
mixFactor = 0.5f * gravityAngle / MIN_GRAVITY_ANGLE;
}
deltaRotation = safeMix(deltaRotation, gravityDelta, mixFactor);
}
*/
// Apply the rotation, but use mixRotationDelta() which blends a bit of the default pose
// at in the process. This provides stability to the IK solution and removes the necessity
// for the gravity effect.
glm::quat oldNextRotation = nextState.getRotation();
float mixFactor = 0.03f;
nextState.mixRotationDelta(deltaRotation, mixFactor, priority);
// measure the result of the rotation which may have been modified by
// blending and constraints
glm::quat actualDelta = nextState.getRotation() * glm::inverse(oldNextRotation);
endPosition = pivot + actualDelta * leverArm;
}
// recompute transforms from the top down
glm::mat4 parentTransform = topParentTransform;
for (int j = numFree - 1; j >= 0; --j) {
JointState& freeState = _jointStates[freeLineage.at(j)];
freeState.computeTransform(parentTransform);
parentTransform = freeState.getTransform();
}
// measure our success
endPosition = endState.getPosition();
distanceToGo = glm::distance(targetPosition, endPosition);
} while (numIterations < MAX_ITERATION_COUNT && distanceToGo < ACCEPTABLE_IK_ERROR);
// set final rotation of the end joint
endState.setRotationFromBindFrame(targetRotation, priority);
_shapesAreDirty = !_shapes.isEmpty();
}
bool Model::restoreJointPosition(int jointIndex, float fraction, float priority) {
if (jointIndex == -1 || _jointStates.isEmpty()) {
return false;
@ -1605,7 +1769,7 @@ void AnimationHandle::applyFrame(float frameIndex) {
if (mapping != -1) {
JointState& state = _model->_jointStates[mapping];
if (_priority >= state._animationPriority) {
state._rotationInParentFrame = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
state.setRotationInParentFrame(safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction));
state._animationPriority = _priority;
}
}

View file

@ -120,6 +120,9 @@ public:
bool getJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
bool getJointCombinedRotation(int jointIndex, glm::quat& rotation) const;
bool getVisibleJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const;
bool getVisibleJointRotationInWorldFrame(int jointIndex, glm::quat& rotation) const;
/// \param jointIndex index of joint in model structure
/// \param position[out] position of joint in model-frame
/// \return true if joint exists
@ -152,6 +155,7 @@ protected:
bool _snapModelToCenter; /// is the model's offset automatically adjusted to center around 0,0,0 in model space
bool _snappedToCenter; /// are we currently snapped to center
bool _showTrueJointTransforms;
int _rootIndex;
QVector<JointState> _jointStates;
@ -176,6 +180,8 @@ protected:
/// Updates the state of the joint at the specified index.
virtual void updateJointState(int index);
virtual void updateVisibleJointStates();
/// \param jointIndex index of joint in model structure
/// \param position position of joint in model-frame
@ -188,6 +194,8 @@ protected:
bool setJointPosition(int jointIndex, const glm::vec3& position, const glm::quat& rotation = glm::quat(),
bool useRotation = false, int lastFreeIndex = -1, bool allIntermediatesFree = false,
const glm::vec3& alignment = glm::vec3(0.0f, -1.0f, 0.0f), float priority = 1.0f);
void inverseKinematics(int jointIndex, glm::vec3 position, const glm::quat& rotation, float priority);
/// Restores the indexed joint to its default position.
/// \param fraction the fraction of the default position to apply (i.e., 0.25f to slerp one fourth of the way to

View file

@ -85,6 +85,33 @@ void TextureCache::setFrameBufferSize(QSize frameBufferSize) {
}
}
// use fixed table of permutations. Could also make ordered list programmatically
// and then shuffle algorithm. For testing, this ensures consistent behavior in each run.
// this list taken from Ken Perlin's Improved Noise reference implementation (orig. in Java) at
// http://mrl.nyu.edu/~perlin/noise/
const int permutation[256] =
{
151, 160, 137, 91, 90, 15, 131, 13, 201, 95, 96, 53, 194, 233, 7, 225,
140, 36, 103, 30, 69, 142, 8, 99, 37, 240, 21, 10, 23, 190, 6, 148,
247, 120, 234, 75, 0, 26, 197, 62, 94, 252, 219, 203, 117, 35, 11, 32,
57, 177, 33, 88, 237, 149, 56, 87, 174, 20, 125, 136, 171, 168, 68, 175,
74, 165, 71, 134, 139, 48, 27, 166, 77, 146, 158, 231, 83, 111, 229, 122,
60, 211, 133, 230, 220, 105, 92, 41, 55, 46, 245, 40, 244, 102, 143, 54,
65, 25, 63, 161, 1, 216, 80, 73, 209, 76, 132, 187, 208, 89, 18, 169,
200, 196, 135, 130, 116, 188, 159, 86, 164, 100, 109, 198, 173, 186, 3, 64,
52, 217, 226, 250, 124, 123, 5, 202, 38, 147, 118, 126, 255, 82, 85, 212,
207, 206, 59, 227, 47, 16, 58, 17, 182, 189, 28, 42, 223, 183, 170, 213,
119, 248, 152, 2, 44, 154, 163, 70, 221, 153, 101, 155, 167, 43, 172, 9,
129, 22, 39, 253, 19, 98, 108, 110, 79, 113, 224, 232, 178, 185, 112, 104,
218, 246, 97, 228, 251, 34, 242, 193, 238, 210, 144, 12, 191, 179, 162, 241,
81, 51, 145, 235, 249, 14, 239, 107, 49, 192, 214, 31, 181, 199, 106, 157,
184, 84, 204, 176, 115, 121, 50, 45, 127, 4, 150, 254, 138, 236, 205, 93,
222, 114, 67, 29, 24, 72, 243, 141, 128, 195, 78, 66, 215, 61, 156, 180
};
#define USE_CHRIS_NOISE 1
GLuint TextureCache::getPermutationNormalTextureID() {
if (_permutationNormalTextureID == 0) {
glGenTextures(1, &_permutationNormalTextureID);
@ -92,10 +119,17 @@ GLuint TextureCache::getPermutationNormalTextureID() {
// the first line consists of random permutation offsets
unsigned char data[256 * 2 * 3];
#if (USE_CHRIS_NOISE==1)
for (int i = 0; i < 256; i++) {
data[3*i+0] = permutation[i];
data[3*i+1] = permutation[i];
data[3*i+2] = permutation[i];
#else
for (int i = 0; i < 256 * 3; i++) {
data[i] = rand() % 256;
#endif
}
// the next, random unit normals
for (int i = 256 * 3; i < 256 * 3 * 2; i += 3) {
glm::vec3 randvec = glm::sphericalRand(1.0f);
data[i] = ((randvec.x + 1.0f) / 2.0f) * 255.0f;
@ -105,7 +139,6 @@ GLuint TextureCache::getPermutationNormalTextureID() {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 256, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
glBindTexture(GL_TEXTURE_2D, 0);
}
return _permutationNormalTextureID;

View file

@ -41,8 +41,7 @@ ApplicationOverlay::ApplicationOverlay() :
_textureFov(DEFAULT_OCULUS_UI_ANGULAR_SIZE * RADIANS_PER_DEGREE),
_alpha(1.0f),
_active(true),
_crosshairTexture(0)
{
_crosshairTexture(0) {
memset(_reticleActive, 0, sizeof(_reticleActive));
memset(_magActive, 0, sizeof(_reticleActive));
@ -206,7 +205,7 @@ void ApplicationOverlay::getClickLocation(int &x, int &y) const {
}
}
// Draws the FBO texture for Oculus rift. TODO: Draw a curved texture instead of plane.
// Draws the FBO texture for Oculus rift.
void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
if (_alpha == 0.0f) {
@ -293,6 +292,107 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
}
// Draws the FBO texture for 3DTV.
void ApplicationOverlay::displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov) {
if (_alpha == 0.0f) {
return;
}
Application* application = Application::getInstance();
MyAvatar* myAvatar = application->getAvatar();
const glm::vec3& viewMatrixTranslation = application->getViewMatrixTranslation();
glActiveTexture(GL_TEXTURE0);
glEnable(GL_BLEND);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glBindTexture(GL_TEXTURE_2D, getFramebufferObject()->texture());
glEnable(GL_DEPTH_TEST);
glDisable(GL_LIGHTING);
glEnable(GL_TEXTURE_2D);
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
// Transform to world space
glm::quat rotation = whichCamera.getRotation();
glm::vec3 axis2 = glm::axis(rotation);
glRotatef(-glm::degrees(glm::angle(rotation)), axis2.x, axis2.y, axis2.z);
glTranslatef(viewMatrixTranslation.x, viewMatrixTranslation.y, viewMatrixTranslation.z);
// Translate to the front of the camera
glm::vec3 pos = whichCamera.getPosition();
glm::quat rot = myAvatar->getOrientation();
glm::vec3 axis = glm::axis(rot);
glTranslatef(pos.x, pos.y, pos.z);
glRotatef(glm::degrees(glm::angle(rot)), axis.x, axis.y, axis.z);
glColor4f(1.0f, 1.0f, 1.0f, _alpha);
//Render
// fov -= RADIANS_PER_DEGREE * 2.5f; //reduce by 5 degrees so it fits in the view
const GLfloat distance = 1.0f;
const GLfloat halfQuadHeight = distance * tan(fov);
const GLfloat halfQuadWidth = halfQuadHeight * aspectRatio;
const GLfloat quadWidth = halfQuadWidth * 2.0f;
const GLfloat quadHeight = halfQuadHeight * 2.0f;
GLfloat x = -halfQuadWidth;
GLfloat y = -halfQuadHeight;
glDisable(GL_DEPTH_TEST);
glBegin(GL_QUADS);
glTexCoord2f(0.0f, 1.0f); glVertex3f(x, y + quadHeight, -distance);
glTexCoord2f(1.0f, 1.0f); glVertex3f(x + quadWidth, y + quadHeight, -distance);
glTexCoord2f(1.0f, 0.0f); glVertex3f(x + quadWidth, y, -distance);
glTexCoord2f(0.0f, 0.0f); glVertex3f(x, y, -distance);
glEnd();
if (_crosshairTexture == 0) {
_crosshairTexture = Application::getInstance()->getGLWidget()->bindTexture(QImage(Application::resourcesPath() + "images/sixense-reticle.png"));
}
//draw the mouse pointer
glBindTexture(GL_TEXTURE_2D, _crosshairTexture);
const float reticleSize = 40.0f / application->getGLWidget()->width() * quadWidth;
x -= reticleSize / 2.0f;
y += reticleSize / 2.0f;
const float mouseX = (application->getMouseX() / (float)application->getGLWidget()->width()) * quadWidth;
const float mouseY = (1.0 - (application->getMouseY() / (float)application->getGLWidget()->height())) * quadHeight;
glBegin(GL_QUADS);
glColor3f(RETICLE_COLOR[0], RETICLE_COLOR[1], RETICLE_COLOR[2]);
glTexCoord2d(0.0f, 0.0f); glVertex3f(x + mouseX, y + mouseY, -distance);
glTexCoord2d(1.0f, 0.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY, -distance);
glTexCoord2d(1.0f, 1.0f); glVertex3f(x + mouseX + reticleSize, y + mouseY - reticleSize, -distance);
glTexCoord2d(0.0f, 1.0f); glVertex3f(x + mouseX, y + mouseY - reticleSize, -distance);
glEnd();
glEnable(GL_DEPTH_TEST);
glPopMatrix();
glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
glDisable(GL_TEXTURE_2D);
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glEnable(GL_LIGHTING);
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
}
//Renders optional pointers
void ApplicationOverlay::renderPointers() {
Application* application = Application::getInstance();

View file

@ -29,6 +29,7 @@ public:
void renderOverlay(bool renderToTexture = false);
void displayOverlayTexture();
void displayOverlayTextureOculus(Camera& whichCamera);
void displayOverlayTexture3DTV(Camera& whichCamera, float aspectRatio, float fov);
void computeOculusPickRay(float x, float y, glm::vec3& direction) const;
void getClickLocation(int &x, int &y) const;

View file

@ -14,10 +14,11 @@
#include <QGridLayout>
#include <QHeaderView>
#include <QMessageBox>
#include <QNetworkAccessManager>
#include <QUrl>
#include <QXmlStreamReader>
#include <NetworkAccessManager.h>
#include "Application.h"
#include "ModelsBrowser.h"
@ -210,10 +211,10 @@ void ModelHandler::update() {
}
for (int i = 0; i < _model.rowCount(); ++i) {
QUrl url(_model.item(i,0)->data(Qt::UserRole).toString());
QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
accessManager->head(request);
connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
QNetworkReply* reply = networkAccessManager.head(request);
connect(reply, SIGNAL(finished()), SLOT(processCheck()));
}
_lock.unlock();
}
@ -233,7 +234,8 @@ void ModelHandler::exit() {
_lock.unlock();
}
void ModelHandler::downloadFinished(QNetworkReply* reply) {
void ModelHandler::downloadFinished() {
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
QByteArray data = reply->readAll();
if (!data.isEmpty()) {
@ -261,10 +263,10 @@ void ModelHandler::queryNewFiles(QString marker) {
// Download
url.setQuery(query);
QNetworkAccessManager* accessManager = new QNetworkAccessManager(this);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request(url);
accessManager->get(request);
connect(accessManager, SIGNAL(finished(QNetworkReply*)), SLOT(downloadFinished(QNetworkReply*)));
QNetworkReply* reply = networkAccessManager.get(request);
connect(reply, SIGNAL(finished()), SLOT(processCheck()));
}

View file

@ -43,7 +43,7 @@ public slots:
void exit();
private slots:
void downloadFinished(QNetworkReply* reply);
void downloadFinished();
private:
bool _initiateExit;

View file

@ -148,8 +148,8 @@ void ScriptEditorWidget::loadFile(const QString& scriptPath) {
disconnect(_scriptEngine, &ScriptEngine::finished, this, &ScriptEditorWidget::onScriptFinished);
}
} else {
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
qDebug() << "Downloading included script at" << scriptPath;
QEventLoop loop;
QObject::connect(reply, &QNetworkReply::finished, &loop, &QEventLoop::quit);

View file

@ -40,8 +40,7 @@ Q_DECLARE_METATYPE(QNetworkAccessManager::Operation)
SnapshotShareDialog::SnapshotShareDialog(QString fileName, QWidget* parent) :
QDialog(parent),
_fileName(fileName),
_networkAccessManager(NULL)
_fileName(fileName)
{
setAttribute(Qt::WA_DeleteOnClose);
@ -92,10 +91,6 @@ void SnapshotShareDialog::uploadSnapshot() {
return;
}
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
QHttpMultiPart* multiPart = new QHttpMultiPart(QHttpMultiPart::FormDataType);
QHttpPart apiKeyPart;
@ -118,9 +113,7 @@ void SnapshotShareDialog::uploadSnapshot() {
QUrl url(FORUM_UPLOADS_URL);
QNetworkRequest request(url);
QNetworkReply* reply = _networkAccessManager->post(request, multiPart);
QNetworkReply* reply = NetworkAccessManager::getInstance().post(request, multiPart);
connect(reply, &QNetworkReply::finished, this, &SnapshotShareDialog::uploadRequestFinished);
QEventLoop loop;
@ -129,11 +122,6 @@ void SnapshotShareDialog::uploadSnapshot() {
}
void SnapshotShareDialog::sendForumPost(QString snapshotPath) {
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
// post to Discourse forum
QNetworkRequest request;
QUrl forumUrl(FORUM_POST_URL);
@ -148,7 +136,7 @@ void SnapshotShareDialog::sendForumPost(QString snapshotPath) {
request.setUrl(forumUrl);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
QNetworkReply* requestReply = NetworkAccessManager::getInstance().post(request, postData);
connect(requestReply, &QNetworkReply::finished, this, &SnapshotShareDialog::postRequestFinished);
QEventLoop loop;

View file

@ -14,7 +14,6 @@
#include "ui_shareSnapshot.h"
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QUrl>
@ -26,7 +25,6 @@ public:
private:
QString _fileName;
QNetworkAccessManager* _networkAccessManager;
Ui_SnapshotShareDialog _ui;
void uploadSnapshot();

View file

@ -0,0 +1,77 @@
//
// UserLocationsDialog.cpp
// interface/src/ui
//
// Created by Ryan Huffman on 06/24/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QDebug>
#include <QInputDialog>
#include <QPushButton>
#include "Menu.h"
#include "UserLocationsDialog.h"
UserLocationsDialog::UserLocationsDialog(QWidget* parent) :
QDialog(parent),
_ui(),
_proxyModel(this),
_userLocationsModel(this) {
_ui.setupUi(this);
_proxyModel.setSourceModel(&_userLocationsModel);
_proxyModel.setDynamicSortFilter(true);
_ui.locationsTreeView->setModel(&_proxyModel);
_ui.locationsTreeView->setSortingEnabled(true);
_ui.locationsTreeView->sortByColumn(UserLocationsModel::NameColumn, Qt::AscendingOrder);
connect(_ui.locationsTreeView->selectionModel(), &QItemSelectionModel::selectionChanged,
this, &UserLocationsDialog::updateEnabled);
connect(&_userLocationsModel, &UserLocationsModel::modelReset, this, &UserLocationsDialog::updateEnabled);
connect(&_userLocationsModel, &UserLocationsModel::modelReset, &_proxyModel, &QSortFilterProxyModel::invalidate);
connect(_ui.locationsTreeView, &QTreeView::doubleClicked, this, &UserLocationsDialog::goToModelIndex);
connect(_ui.deleteButton, &QPushButton::clicked, this, &UserLocationsDialog::deleteSelection);
connect(_ui.renameButton, &QPushButton::clicked, this, &UserLocationsDialog::renameSelection);
connect(_ui.refreshButton, &QPushButton::clicked, &_userLocationsModel, &UserLocationsModel::refresh);
this->setWindowTitle("My Locations");
}
void UserLocationsDialog::updateEnabled() {
bool enabled = _ui.locationsTreeView->selectionModel()->hasSelection();
_ui.renameButton->setEnabled(enabled);
_ui.deleteButton->setEnabled(enabled);
}
void UserLocationsDialog::goToModelIndex(const QModelIndex& index) {
QVariant location = _proxyModel.data(index.sibling(index.row(), UserLocationsModel::LocationColumn));
Menu::getInstance()->goToURL(location.toString());
}
void UserLocationsDialog::deleteSelection() {
QModelIndex selection = _ui.locationsTreeView->selectionModel()->currentIndex();
selection = _proxyModel.mapToSource(selection);
if (selection.isValid()) {
_userLocationsModel.deleteLocation(selection);
}
}
void UserLocationsDialog::renameSelection() {
QModelIndex selection = _ui.locationsTreeView->selectionModel()->currentIndex();
selection = _proxyModel.mapToSource(selection);
if (selection.isValid()) {
bool ok;
QString name = _userLocationsModel.data(selection.sibling(selection.row(), UserLocationsModel::NameColumn)).toString();
QString newName = QInputDialog::getText(this, "Rename '" + name + "'", "Set name to:", QLineEdit::Normal, name, &ok);
if (ok && !newName.isEmpty()) {
_userLocationsModel.renameLocation(selection, newName);
}
}
}

View file

@ -0,0 +1,35 @@
//
// UserLocationsDialog.h
// interface/src/ui
//
// Created by Ryan Huffman on 06/24/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_UserLocationsDialog_h
#define hifi_UserLocationsDialog_h
#include "ui_userLocationsDialog.h"
#include "UserLocationsModel.h"
class UserLocationsDialog : public QDialog {
Q_OBJECT
public:
UserLocationsDialog(QWidget* parent = NULL);
protected slots:
void updateEnabled();
void goToModelIndex(const QModelIndex& index);
void deleteSelection();
void renameSelection();
private:
Ui::UserLocationsDialog _ui;
QSortFilterProxyModel _proxyModel;
UserLocationsModel _userLocationsModel;
};
#endif // hifi_UserLocationsDialog_h

View file

@ -14,8 +14,7 @@
#include "BillboardOverlay.h"
BillboardOverlay::BillboardOverlay()
: _manager(NULL),
_scale(1.0f),
: _scale(1.0f),
_isFacingAvatar(true) {
}
@ -119,18 +118,13 @@ void BillboardOverlay::setProperties(const QScriptValue &properties) {
}
}
// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
void BillboardOverlay::setBillboardURL(const QUrl url) {
// TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made?
_manager->deleteLater();
_manager = new QNetworkAccessManager();
connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
_manager->get(QNetworkRequest(url));
QNetworkReply* reply = NetworkAccessManager::getInstance().get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &BillboardOverlay::replyFinished);
}
void BillboardOverlay::replyFinished(QNetworkReply* reply) {
void BillboardOverlay::replyFinished() {
// replace our byte array with the downloaded data
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
_billboard = reply->readAll();
_manager->deleteLater();
_manager = NULL;
}

View file

@ -27,12 +27,11 @@ public:
virtual void setProperties(const QScriptValue& properties);
private slots:
void replyFinished(QNetworkReply* reply);
void replyFinished();
private:
void setBillboardURL(const QUrl url);
QNetworkAccessManager* _manager;
QUrl _url;
QByteArray _billboard;
QSize _size;

View file

@ -19,7 +19,6 @@
#include "ImageOverlay.h"
ImageOverlay::ImageOverlay() :
_manager(NULL),
_textureID(0),
_renderImage(false),
_textureBound(false),
@ -36,21 +35,18 @@ ImageOverlay::~ImageOverlay() {
// TODO: handle setting image multiple times, how do we manage releasing the bound texture?
void ImageOverlay::setImageURL(const QUrl& url) {
// TODO: are we creating too many QNetworkAccessManager() when multiple calls to setImageURL are made?
_manager->deleteLater();
_manager = new QNetworkAccessManager();
connect(_manager, SIGNAL(finished(QNetworkReply*)), this, SLOT(replyFinished(QNetworkReply*)));
_manager->get(QNetworkRequest(url));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
connect(reply, &QNetworkReply::finished, this, &ImageOverlay::replyFinished);
}
void ImageOverlay::replyFinished(QNetworkReply* reply) {
void ImageOverlay::replyFinished() {
QNetworkReply* reply = static_cast<QNetworkReply*>(sender());
// replace our byte array with the downloaded data
QByteArray rawData = reply->readAll();
_textureImage.loadFromData(rawData);
_renderImage = true;
_manager->deleteLater();
_manager = NULL;
}
void ImageOverlay::render() {

View file

@ -16,13 +16,13 @@
#include <QGLWidget>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRect>
#include <QScriptValue>
#include <QString>
#include <QUrl>
#include <NetworkAccessManager.h>
#include <SharedUtil.h>
#include "Overlay.h"
@ -46,13 +46,12 @@ public:
virtual void setProperties(const QScriptValue& properties);
private slots:
void replyFinished(QNetworkReply* reply); // we actually want to hide this...
void replyFinished(); // we actually want to hide this...
private:
QUrl _imageURL;
QImage _textureImage;
QNetworkAccessManager* _manager;
GLuint _textureID;
QRect _fromImage; // where from in the image to sample

View file

@ -84,13 +84,13 @@ void Overlays::render3D() {
return;
}
bool myAvatarComputed = false;
MyAvatar* avatar;
MyAvatar* avatar = NULL;
glm::quat myAvatarRotation;
glm::vec3 myAvatarPosition;
float angle;
glm::vec3 axis;
float myAvatarScale;
glm::vec3 myAvatarPosition(0.0f);
float angle = 0.0f;
glm::vec3 axis(0.0f, 1.0f, 0.0f);
float myAvatarScale = 1.0f;
foreach(Overlay* thisOverlay, _overlays3D) {
glPushMatrix();
switch (thisOverlay->getAnchor()) {

View file

@ -16,7 +16,6 @@
#include <QGLWidget>
#include <QImage>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QRect>
#include <QScriptValue>

View file

@ -0,0 +1,130 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>UserLocationsDialog</class>
<widget class="QWidget" name="UserLocationsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>929</width>
<height>633</height>
</rect>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<widget class="QWidget" name="widget_2" native="true">
<layout class="QHBoxLayout" name="horizontalLayout_2">
<item>
<widget class="QLabel" name="label">
<property name="styleSheet">
<string notr="true">font-size: 16px</string>
</property>
<property name="text">
<string>My Locations</string>
</property>
</widget>
</item>
<item>
<spacer name="horizontalSpacer_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="refreshButton">
<property name="text">
<string>Refresh</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QTreeView" name="locationsTreeView">
<property name="indentation">
<number>0</number>
</property>
<property name="rootIsDecorated">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>-1</number>
</property>
<property name="leftMargin">
<number>12</number>
</property>
<property name="topMargin">
<number>12</number>
</property>
<property name="rightMargin">
<number>12</number>
</property>
<property name="bottomMargin">
<number>12</number>
</property>
<item>
<spacer name="horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="renameButton">
<property name="text">
<string>Rename</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="deleteButton">
<property name="text">
<string>Delete</string>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>

View file

@ -12,6 +12,9 @@ set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/../../cm
set(TARGET_NAME audio)
find_package(Qt5 COMPONENTS Script)
include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
# set up the external glm library
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
@ -26,4 +29,4 @@ link_hifi_library(networking ${TARGET_NAME} "${ROOT_DIR}")
# add a definition for ssize_t so that windows doesn't bail
if (WIN32)
add_definitions(-Dssize_t=long)
endif ()
endif ()

View file

@ -53,7 +53,7 @@ void AudioRingBuffer::reset() {
_isStarved = true;
}
void AudioRingBuffer::resizeForFrameSize(qint64 numFrameSamples) {
void AudioRingBuffer::resizeForFrameSize(int numFrameSamples) {
delete[] _buffer;
_sampleCapacity = numFrameSamples * RING_BUFFER_LENGTH_FRAMES;
_buffer = new int16_t[_sampleCapacity];
@ -70,14 +70,14 @@ int AudioRingBuffer::parseData(const QByteArray& packet) {
return writeData(packet.data() + numBytesBeforeAudioData, packet.size() - numBytesBeforeAudioData);
}
qint64 AudioRingBuffer::readSamples(int16_t* destination, qint64 maxSamples) {
int AudioRingBuffer::readSamples(int16_t* destination, int maxSamples) {
return readData((char*) destination, maxSamples * sizeof(int16_t));
}
qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
int AudioRingBuffer::readData(char *data, int maxSize) {
// only copy up to the number of samples we have available
int numReadSamples = std::min((unsigned) (maxSize / sizeof(int16_t)), samplesAvailable());
int numReadSamples = std::min((int) (maxSize / sizeof(int16_t)), samplesAvailable());
// If we're in random access mode, then we consider our number of available read samples slightly
// differently. Namely, if anything has been written, we say we have as many samples as they ask for
@ -118,14 +118,14 @@ qint64 AudioRingBuffer::readData(char *data, qint64 maxSize) {
return numReadSamples * sizeof(int16_t);
}
qint64 AudioRingBuffer::writeSamples(const int16_t* source, qint64 maxSamples) {
int AudioRingBuffer::writeSamples(const int16_t* source, int maxSamples) {
return writeData((const char*) source, maxSamples * sizeof(int16_t));
}
qint64 AudioRingBuffer::writeData(const char* data, qint64 maxSize) {
int AudioRingBuffer::writeData(const char* data, int maxSize) {
// make sure we have enough bytes left for this to be the right amount of audio
// otherwise we should not copy that data, and leave the buffer pointers where they are
int samplesToCopy = std::min((quint64)(maxSize / sizeof(int16_t)), (quint64)_sampleCapacity);
int samplesToCopy = std::min((int)(maxSize / sizeof(int16_t)), _sampleCapacity);
int samplesRoomFor = _sampleCapacity - samplesAvailable();
if (samplesToCopy > samplesRoomFor) {
@ -167,7 +167,7 @@ void AudioRingBuffer::shiftReadPosition(unsigned int numSamples) {
}
}
unsigned int AudioRingBuffer::samplesAvailable() const {
int AudioRingBuffer::samplesAvailable() const {
if (!_endOfLastWrite) {
return 0;
}
@ -208,7 +208,7 @@ int AudioRingBuffer::addSilentFrame(int numSilentSamples) {
return numSilentSamples * sizeof(int16_t);
}
bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const {
bool AudioRingBuffer::isNotStarvedOrHasMinimumSamples(int numRequiredSamples) const {
if (!_isStarved) {
return true;
} else {

View file

@ -43,7 +43,7 @@ public:
~AudioRingBuffer();
void reset();
void resizeForFrameSize(qint64 numFrameSamples);
void resizeForFrameSize(int numFrameSamples);
int getSampleCapacity() const { return _sampleCapacity; }
@ -53,20 +53,20 @@ public:
const int16_t* getNextOutput() const { return _nextOutput; }
const int16_t* getBuffer() const { return _buffer; }
qint64 readSamples(int16_t* destination, qint64 maxSamples);
qint64 writeSamples(const int16_t* source, qint64 maxSamples);
int readSamples(int16_t* destination, int maxSamples);
int writeSamples(const int16_t* source, int maxSamples);
qint64 readData(char* data, qint64 maxSize);
qint64 writeData(const char* data, qint64 maxSize);
int readData(char* data, int maxSize);
int writeData(const char* data, int maxSize);
int16_t& operator[](const int index);
const int16_t& operator[] (const int index) const;
void shiftReadPosition(unsigned int numSamples);
unsigned int samplesAvailable() const;
int samplesAvailable() const;
bool isNotStarvedOrHasMinimumSamples(unsigned int numRequiredSamples) const;
bool isNotStarvedOrHasMinimumSamples(int numRequiredSamples) const;
bool isStarved() const { return _isStarved; }
void setIsStarved(bool isStarved) { _isStarved = isStarved; }

View file

@ -212,7 +212,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
}
return false;
} else if (samplesAvailable() < (unsigned int)samplesPerFrame) {
} else if (samplesAvailable() < samplesPerFrame) {
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
_isStarved = true;

View file

@ -15,12 +15,12 @@
#include <QDataStream>
#include <QtCore/QDebug>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <qendian.h>
#include <LimitedNodeList.h>
#include <NetworkAccessManager.h>
#include <SharedUtil.h>
#include "AudioRingBuffer.h"
@ -73,11 +73,11 @@ Sound::Sound(const QUrl& sampleURL, QObject* parent) :
// assume we have a QApplication or QCoreApplication instance and use the
// QNetworkAccess manager to grab the raw audio file at the given URL
QNetworkAccessManager *manager = new QNetworkAccessManager(this);
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
qDebug() << "Requesting audio file" << sampleURL.toDisplayString();
QNetworkReply* soundDownload = manager->get(QNetworkRequest(sampleURL));
QNetworkReply* soundDownload = networkAccessManager.get(QNetworkRequest(sampleURL));
connect(soundDownload, &QNetworkReply::finished, this, &Sound::replyFinished);
connect(soundDownload, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(replyError(QNetworkReply::NetworkError)));
}

View file

@ -16,10 +16,10 @@
#include <QtCore/QDataStream>
#include <QtCore/QThread>
#include <QtCore/QUuid>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
#include <NetworkAccessManager.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <SharedUtil.h>
@ -33,8 +33,6 @@ quint64 DEFAULT_FILTERED_LOG_EXPIRY = 2 * USECS_PER_SECOND;
using namespace std;
QNetworkAccessManager* AvatarData::networkAccessManager = NULL;
AvatarData::AvatarData() :
_sessionUUID(),
_handPosition(0,0,0),
@ -751,18 +749,15 @@ void AvatarData::setBillboard(const QByteArray& billboard) {
void AvatarData::setBillboardFromURL(const QString &billboardURL) {
_billboardURL = billboardURL;
if (AvatarData::networkAccessManager) {
qDebug() << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL);
QNetworkRequest billboardRequest;
billboardRequest.setUrl(QUrl(billboardURL));
QNetworkReply* networkReply = AvatarData::networkAccessManager->get(billboardRequest);
connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply()));
} else {
qDebug() << "Billboard PNG download requested but no network access manager is available.";
}
qDebug() << "Changing billboard for avatar to PNG at" << qPrintable(billboardURL);
QNetworkRequest billboardRequest;
billboardRequest.setUrl(QUrl(billboardURL));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* networkReply = networkAccessManager.get(billboardRequest);
connect(networkReply, SIGNAL(finished()), this, SLOT(setBillboardFromNetworkReply()));
}
void AvatarData::setBillboardFromNetworkReply() {
@ -839,8 +834,9 @@ void AvatarData::updateJointMappings() {
_jointIndices.clear();
_jointNames.clear();
if (networkAccessManager && _skeletonModelURL.fileName().toLower().endsWith(".fst")) {
QNetworkReply* networkReply = networkAccessManager->get(QNetworkRequest(_skeletonModelURL));
if (_skeletonModelURL.fileName().toLower().endsWith(".fst")) {
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* networkReply = networkAccessManager.get(QNetworkRequest(_skeletonModelURL));
connect(networkReply, SIGNAL(finished()), this, SLOT(setJointMappingsFromNetworkReply()));
}
}

View file

@ -102,7 +102,6 @@ enum KeyState {
const glm::vec3 vec3Zero(0.0f);
class QDataStream;
class QNetworkAccessManager;
class AttachmentData;
class JointData;
@ -269,8 +268,6 @@ public:
QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; }
virtual float getBoundingRadius() const { return 1.f; }
static void setNetworkAccessManager(QNetworkAccessManager* sharedAccessManager) { networkAccessManager = sharedAccessManager; }
public slots:
void sendIdentityPacket();
@ -323,8 +320,6 @@ protected:
QHash<QString, int> _jointIndices; ///< 1-based, since zero is returned for missing keys
QStringList _jointNames; ///< in order of depth-first traversal
static QNetworkAccessManager* networkAccessManager;
quint64 _errorLogExpiry; ///< time in future when to log an error

View file

@ -37,19 +37,20 @@ Q_DECLARE_METATYPE(JSONCallbackParameters)
const QString ACCOUNTS_GROUP = "accounts";
JSONCallbackParameters::JSONCallbackParameters() :
jsonCallbackReceiver(NULL),
jsonCallbackMethod(),
errorCallbackReceiver(NULL),
errorCallbackMethod(),
updateReciever(NULL),
updateSlot()
JSONCallbackParameters::JSONCallbackParameters(QObject* jsonCallbackReceiver, const QString& jsonCallbackMethod,
QObject* errorCallbackReceiver, const QString& errorCallbackMethod,
QObject* updateReceiver, const QString& updateSlot) :
jsonCallbackReceiver(jsonCallbackReceiver),
jsonCallbackMethod(jsonCallbackMethod),
errorCallbackReceiver(errorCallbackReceiver),
errorCallbackMethod(errorCallbackMethod),
updateReciever(updateReceiver),
updateSlot(updateSlot)
{
}
AccountManager::AccountManager() :
_authURL(),
_networkAccessManager(NULL),
_pendingCallbackMap(),
_accountInfo()
{
@ -153,9 +154,7 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
const JSONCallbackParameters& callbackParams,
const QByteArray& dataByteArray, QHttpMultiPart* dataMultiPart) {
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
if (hasValidAccessToken()) {
QNetworkRequest authenticatedRequest;
@ -184,26 +183,29 @@ void AccountManager::invokedRequest(const QString& path, QNetworkAccessManager::
switch (operation) {
case QNetworkAccessManager::GetOperation:
networkReply = _networkAccessManager->get(authenticatedRequest);
networkReply = networkAccessManager.get(authenticatedRequest);
break;
case QNetworkAccessManager::PostOperation:
case QNetworkAccessManager::PutOperation:
if (dataMultiPart) {
if (operation == QNetworkAccessManager::PostOperation) {
networkReply = _networkAccessManager->post(authenticatedRequest, dataMultiPart);
networkReply = networkAccessManager.post(authenticatedRequest, dataMultiPart);
} else {
networkReply = _networkAccessManager->put(authenticatedRequest, dataMultiPart);
networkReply = networkAccessManager.put(authenticatedRequest, dataMultiPart);
}
dataMultiPart->setParent(networkReply);
} else {
authenticatedRequest.setHeader(QNetworkRequest::ContentTypeHeader, "application/json");
if (operation == QNetworkAccessManager::PostOperation) {
networkReply = _networkAccessManager->post(authenticatedRequest, dataByteArray);
networkReply = networkAccessManager.post(authenticatedRequest, dataByteArray);
} else {
networkReply = _networkAccessManager->put(authenticatedRequest, dataByteArray);
networkReply = networkAccessManager.put(authenticatedRequest, dataByteArray);
}
}
break;
case QNetworkAccessManager::DeleteOperation:
networkReply = networkAccessManager.sendCustomRequest(authenticatedRequest, "DELETE");
break;
default:
// other methods not yet handled
@ -304,9 +306,7 @@ bool AccountManager::checkAndSignalForAccessToken() {
void AccountManager::requestAccessToken(const QString& login, const QString& password) {
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkRequest request;
@ -324,7 +324,7 @@ void AccountManager::requestAccessToken(const QString& login, const QString& pas
request.setUrl(grantURL);
request.setHeader(QNetworkRequest::ContentTypeHeader, "application/x-www-form-urlencoded");
QNetworkReply* requestReply = _networkAccessManager->post(request, postData);
QNetworkReply* requestReply = networkAccessManager.post(request, postData);
connect(requestReply, &QNetworkReply::finished, this, &AccountManager::requestAccessTokenFinished);
connect(requestReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestAccessTokenError(QNetworkReply::NetworkError)));
}
@ -376,15 +376,13 @@ void AccountManager::requestAccessTokenError(QNetworkReply::NetworkError error)
}
void AccountManager::requestProfile() {
if (!_networkAccessManager) {
_networkAccessManager = new QNetworkAccessManager(this);
}
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QUrl profileURL = _authURL;
profileURL.setPath("/api/v1/users/profile");
profileURL.setQuery("access_token=" + _accountInfo.getAccessToken().token);
QNetworkReply* profileReply = _networkAccessManager->get(QNetworkRequest(profileURL));
QNetworkReply* profileReply = networkAccessManager.get(QNetworkRequest(profileURL));
connect(profileReply, &QNetworkReply::finished, this, &AccountManager::requestProfileFinished);
connect(profileReply, SIGNAL(error(QNetworkReply::NetworkError)), this, SLOT(requestProfileError(QNetworkReply::NetworkError)));
}

View file

@ -15,14 +15,17 @@
#include <QtCore/QByteArray>
#include <QtCore/QObject>
#include <QtCore/QUrl>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include "NetworkAccessManager.h"
#include "DataServerAccountInfo.h"
class JSONCallbackParameters {
public:
JSONCallbackParameters();
JSONCallbackParameters(QObject* jsonCallbackReceiver = NULL, const QString& jsonCallbackMethod = QString(),
QObject* errorCallbackReceiver = NULL, const QString& errorCallbackMethod = QString(),
QObject* updateReceiver = NULL, const QString& updateSlot = QString());
bool isEmpty() const { return !jsonCallbackReceiver && !errorCallbackReceiver; }
@ -58,8 +61,6 @@ public:
const DataServerAccountInfo& getAccountInfo() const { return _accountInfo; }
void destroy() { delete _networkAccessManager; }
public slots:
void requestAccessTokenFinished();
void requestProfileFinished();
@ -93,7 +94,6 @@ private:
QHttpMultiPart* dataMultiPart);
QUrl _authURL;
QNetworkAccessManager* _networkAccessManager;
QMap<QNetworkReply*, JSONCallbackParameters> _pendingCallbackMap;
DataServerAccountInfo _accountInfo;

View file

@ -0,0 +1,149 @@
//
// NetworkAccessManager.cpp
//
//
// Created by Clement on 7/1/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QMetaObject>
#include <QThread>
#include "NetworkAccessManager.h"
NetworkAccessManager& NetworkAccessManager::getInstance() {
static NetworkAccessManager sharedInstance;
return sharedInstance;
}
NetworkAccessManager::NetworkAccessManager() {
}
QNetworkReply* NetworkAccessManager::get(const QNetworkRequest& request) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"get",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request));
return result;
}
return QNetworkAccessManager::get(request);
}
QNetworkReply* NetworkAccessManager::head(const QNetworkRequest& request) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"head",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request));
return result;
}
return QNetworkAccessManager::head(request);
}
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QIODevice* data) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"post",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(QIODevice*, data));
return result;
}
return QNetworkAccessManager::post(request, data);
}
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, const QByteArray& data) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"post",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(const QByteArray, data));
return result;
}
return QNetworkAccessManager::post(request, data);
}
QNetworkReply* NetworkAccessManager::post(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"post",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(QHttpMultiPart*, multiPart));
return result;
}
return QNetworkAccessManager::post(request, multiPart);
}
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QIODevice* data) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"put",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(QIODevice*, data));
return result;
}
return QNetworkAccessManager::put(request, data);
}
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest& request, QHttpMultiPart* multiPart) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"put",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(QHttpMultiPart*, multiPart));
return result;
}
return QNetworkAccessManager::put(request, multiPart);
}
QNetworkReply* NetworkAccessManager::put(const QNetworkRequest & request, const QByteArray & data) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"put",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(const QByteArray, data));
return result;
}
return QNetworkAccessManager::put(request, data);
}
QNetworkReply* NetworkAccessManager::sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data) {
if (QThread::currentThread() != thread()) {
QNetworkReply* result;
QMetaObject::invokeMethod(this,
"sendCustomRequest",
Qt::BlockingQueuedConnection,
Q_RETURN_ARG(QNetworkReply*, result),
Q_ARG(const QNetworkRequest, request),
Q_ARG(const QByteArray, verb),
Q_ARG(QIODevice*, data));
return result;
}
return QNetworkAccessManager::sendCustomRequest(request, verb, data);
}

View file

@ -0,0 +1,41 @@
//
// NetworkAccessManager.h
//
//
// Created by Clement on 7/1/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_NetworkAccessManager_h
#define hifi_NetworkAccessManager_h
#include <QNetworkAccessManager>
#include <QNetworkConfiguration>
#include <QNetworkProxy>
/// Wrapper around QNetworkAccessManager wo that we only use one instance
/// For any other method you should need, make sure to be on the right thread
/// or call the method using QMetaObject::invokeMethod()
class NetworkAccessManager : public QNetworkAccessManager {
Q_OBJECT
public:
static NetworkAccessManager& getInstance();
Q_INVOKABLE QNetworkReply* get(const QNetworkRequest& request);
Q_INVOKABLE QNetworkReply* head(const QNetworkRequest& request);
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QIODevice* data);
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, const QByteArray& data);
Q_INVOKABLE QNetworkReply* post(const QNetworkRequest& request, QHttpMultiPart* multiPart);
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QIODevice* data);
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, QHttpMultiPart* multiPart);
Q_INVOKABLE QNetworkReply* put(const QNetworkRequest& request, const QByteArray& data);
Q_INVOKABLE QNetworkReply* sendCustomRequest(const QNetworkRequest& request, const QByteArray& verb, QIODevice* data = 0);
private:
NetworkAccessManager();
};
#endif // hifi_NetworkAccessManager_h

View file

@ -16,6 +16,8 @@
#include <QTimer>
#include <QtDebug>
#include "NetworkAccessManager.h"
#include "ResourceCache.h"
ResourceCache::ResourceCache(QObject* parent) :
@ -103,8 +105,6 @@ void ResourceCache::requestCompleted(Resource* resource) {
}
}
QNetworkAccessManager* ResourceCache::_networkAccessManager = NULL;
const int DEFAULT_REQUEST_LIMIT = 10;
int ResourceCache::_requestLimit = DEFAULT_REQUEST_LIMIT;
@ -219,7 +219,7 @@ void Resource::init() {
if (_url.isEmpty()) {
_startedLoading = _loaded = true;
} else if (!(_url.isValid() && ResourceCache::getNetworkAccessManager())) {
} else if (!(_url.isValid())) {
_startedLoading = _failedToLoad = true;
}
}
@ -272,7 +272,7 @@ void Resource::handleReplyTimeout() {
}
void Resource::makeRequest() {
_reply = ResourceCache::getNetworkAccessManager()->get(_request);
_reply = NetworkAccessManager::getInstance().get(_request);
connect(_reply, SIGNAL(downloadProgress(qint64,qint64)), SLOT(handleDownloadProgress(qint64,qint64)));
connect(_reply, SIGNAL(error(QNetworkReply::NetworkError)), SLOT(handleReplyError()));

View file

@ -22,7 +22,6 @@
#include <QUrl>
#include <QWeakPointer>
class QNetworkAccessManager;
class QNetworkReply;
class QTimer;
@ -33,10 +32,6 @@ class ResourceCache : public QObject {
Q_OBJECT
public:
static void setNetworkAccessManager(QNetworkAccessManager* manager) { _networkAccessManager = manager; }
static QNetworkAccessManager* getNetworkAccessManager() { return _networkAccessManager; }
static void setRequestLimit(int limit) { _requestLimit = limit; }
static int getRequestLimit() { return _requestLimit; }
@ -76,7 +71,6 @@ private:
QHash<QUrl, QWeakPointer<Resource> > _resources;
int _lastLRUKey;
static QNetworkAccessManager* _networkAccessManager;
static int _requestLimit;
static QList<QPointer<Resource> > _pendingRequests;
static QList<Resource*> _loadingRequests;

View file

@ -83,17 +83,10 @@ void UserActivityLogger::close(int delayTime) {
// In order to get the end of the session, we need to give the account manager enough time to send the packet.
QEventLoop loop;
// Here we connect the callbacks to stop the event loop
JSONCallbackParameters params;
params.jsonCallbackReceiver = &loop;
params.errorCallbackReceiver = &loop;
params.jsonCallbackMethod = "quit";
params.errorCallbackMethod = "quit";
// In case something goes wrong, we also setup a timer so that the delai is not greater than delayTime
QTimer timer;
connect(&timer, &QTimer::timeout, &loop, &QEventLoop::quit);
// Now we can log it
logAction(ACTION_NAME, QJsonObject(), params);
logAction(ACTION_NAME, QJsonObject());
timer.start(delayTime);
loop.exec();
}

View file

@ -183,7 +183,6 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particleA)
// MIN_VALID_SPEED is obtained by computing speed gained at one gravity after the shortest expected frame
const float MIN_EXPECTED_FRAME_PERIOD = 0.0167f; // 1/60th of a second
const float HALTING_SPEED = 9.8 * MIN_EXPECTED_FRAME_PERIOD / (float)(TREE_SCALE);
void ParticleCollisionSystem::updateCollisionWithAvatars(Particle* particle) {
// particles that are in hand, don't collide with avatars

View file

@ -13,7 +13,6 @@
#include <QtCore/QEventLoop>
#include <QtCore/QTimer>
#include <QtCore/QThread>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkReply>
#include <QScriptEngine>
@ -23,6 +22,7 @@
#include <AvatarData.h>
#include <CollisionInfo.h>
#include <ModelsScriptingInterface.h>
#include <NetworkAccessManager.h>
#include <NodeList.h>
#include <PacketHeaders.h>
#include <ParticlesScriptingInterface.h>
@ -142,8 +142,8 @@ ScriptEngine::ScriptEngine(const QUrl& scriptURL,
emit errorMessage("ERROR Loading file:" + fileName);
}
} else {
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
qDebug() << "Downloading included script at" << url;
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));
@ -648,8 +648,8 @@ void ScriptEngine::include(const QString& includeFile) {
QString includeContents;
if (url.scheme() == "http" || url.scheme() == "ftp") {
QNetworkAccessManager* networkManager = new QNetworkAccessManager(this);
QNetworkReply* reply = networkManager->get(QNetworkRequest(url));
NetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
QNetworkReply* reply = networkAccessManager.get(QNetworkRequest(url));
qDebug() << "Downloading included script at" << includeFile;
QEventLoop loop;
QObject::connect(reply, SIGNAL(finished()), &loop, SLOT(quit()));

View file

@ -14,6 +14,8 @@
#include <QEventLoop>
#include <NetworkAccessManager.h>
#include "XMLHttpRequestClass.h"
XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
@ -22,7 +24,6 @@ XMLHttpRequestClass::XMLHttpRequestClass(QScriptEngine* engine) :
_url(),
_method(""),
_responseType(""),
_manager(this),
_request(),
_reply(NULL),
_sendData(NULL),
@ -161,7 +162,7 @@ void XMLHttpRequestClass::send(const QString& data) {
}
void XMLHttpRequestClass::doSend() {
_reply = _manager.sendCustomRequest(_request, _method.toLatin1(), _sendData);
_reply = NetworkAccessManager::getInstance().sendCustomRequest(_request, _method.toLatin1(), _sendData);
connectToReply(_reply);

View file

@ -13,7 +13,6 @@
#define hifi_XMLHttpRequestClass_h
#include <QBuffer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
#include <QNetworkRequest>
#include <QObject>
@ -104,7 +103,6 @@ private:
QUrl _url;
QString _method;
QString _responseType;
QNetworkAccessManager _manager;
QNetworkRequest _request;
QNetworkReply* _reply;
QBuffer* _sendData;

View file

@ -10,7 +10,7 @@ set(MACRO_DIR "${ROOT_DIR}/cmake/macros")
set(TARGET_NAME shared)
project(${TARGET_NAME})
find_package(Qt5 COMPONENTS Network Widgets Xml)
find_package(Qt5 COMPONENTS Network Widgets Xml Script)
include(${MACRO_DIR}/SetupHifiLibrary.cmake)
setup_hifi_library(${TARGET_NAME})
@ -32,4 +32,8 @@ if (UNIX AND NOT APPLE)
target_link_libraries(${TARGET_NAME} "${CMAKE_THREAD_LIBS_INIT}")
endif (UNIX AND NOT APPLE)
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)
# There is something special (bug) about Qt5Scripts, that we have to explicitly add its include
# directory when Qt5 (5.2.1) is compiled from source and is not in a standard place.
include_directories(SYSTEM "${Qt5Script_INCLUDE_DIRS}")
target_link_libraries(${TARGET_NAME} Qt5::Network Qt5::Widgets)

View file

@ -24,9 +24,6 @@ int MAX_ENTITIES_PER_SIMULATION = 64;
int MAX_COLLISIONS_PER_SIMULATION = 256;
const int NUM_SHAPE_BITS = 6;
const int SHAPE_INDEX_MASK = (1 << (NUM_SHAPE_BITS + 1)) - 1;
PhysicsSimulation::PhysicsSimulation() : _collisionList(MAX_COLLISIONS_PER_SIMULATION),
_numIterations(0), _numCollisions(0), _constraintError(0.0f), _stepTime(0) {
}

View file

@ -23,7 +23,7 @@ void SequenceNumberStatsTests::runAllTests() {
pruneTest();
}
const int UINT16_RANGE = std::numeric_limits<quint16>::max() + 1;
const quint32 UINT16_RANGE = std::numeric_limits<quint16>::max() + 1;
void SequenceNumberStatsTests::rolloverTest() {
@ -34,7 +34,7 @@ void SequenceNumberStatsTests::rolloverTest() {
quint16 seq = 79; // start on some random number
for (int R = 0; R < 2; R++) {
for (int i = 0; i < 3 * UINT16_RANGE; i++) {
for (quint32 i = 0; i < 3 * UINT16_RANGE; i++) {
stats.sequenceNumberReceived(seq);
seq = seq + (quint16)1;
@ -53,12 +53,12 @@ void SequenceNumberStatsTests::earlyLateTest() {
SequenceNumberStats stats;
quint16 seq = 65530;
int numSent = 0;
quint32 numSent = 0;
int numEarly = 0;
int numLate = 0;
int numLost = 0;
int numRecovered = 0;
quint32 numEarly = 0;
quint32 numLate = 0;
quint32 numLost = 0;
quint32 numRecovered = 0;
for (int R = 0; R < 2; R++) {
for (int T = 0; T < 10000; T++) {
@ -122,12 +122,12 @@ void SequenceNumberStatsTests::duplicateTest() {
SequenceNumberStats stats;
quint16 seq = 12345;
int numSent = 0;
quint32 numSent = 0;
int numDuplicate = 0;
int numEarly = 0;
int numLate = 0;
int numLost = 0;
quint32 numDuplicate = 0;
quint32 numEarly = 0;
quint32 numLate = 0;
quint32 numLost = 0;
for (int R = 0; R < 2; R++) {
for (int T = 0; T < 10000; T++) {
@ -210,10 +210,10 @@ void SequenceNumberStatsTests::pruneTest() {
SequenceNumberStats stats;
quint16 seq = 54321;
int numSent = 0;
quint32 numSent = 0;
int numEarly = 0;
int numLost = 0;
quint32 numEarly = 0;
quint32 numLost = 0;
for (int R = 0; R < 2; R++) {
for (int T = 0; T < 1000; T++) {