mirror of
https://github.com/overte-org/overte.git
synced 2025-04-13 17:32:11 +02:00
Merge branch 'master' of https://github.com/worklist/hifi into 19508
This commit is contained in:
commit
ada15df89d
14 changed files with 165 additions and 32 deletions
|
@ -92,6 +92,9 @@ void Agent::run() {
|
|||
|
||||
loop.exec();
|
||||
|
||||
// let the AvatarData class use our QNetworkAcessManager
|
||||
AvatarData::setNetworkAccessManager(networkManager);
|
||||
|
||||
QString scriptContents(reply->readAll());
|
||||
|
||||
qDebug() << "Downloaded script:" << scriptContents;
|
||||
|
|
|
@ -50,5 +50,6 @@ if (botNumber <= 20) {
|
|||
// there is no need to change the body model - we're using the default
|
||||
Avatar.faceModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newFaceFilePrefix + ".fst";
|
||||
Avatar.skeletonModelURL = "https://s3-us-west-1.amazonaws.com/highfidelity-public/meshes/" + newBodyFilePrefix + ".fst";
|
||||
Avatar.billboardURL = "https://dl.dropboxusercontent.com/u/1864924/bot-billboard.png";
|
||||
|
||||
Agent.isAvatar = true;
|
|
@ -227,6 +227,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
|
|||
connect(nodeList, SIGNAL(nodeAdded(SharedNodePointer)), &_voxels, SLOT(nodeAdded(SharedNodePointer)));
|
||||
connect(nodeList, SIGNAL(nodeKilled(SharedNodePointer)), &_voxels, SLOT(nodeKilled(SharedNodePointer)));
|
||||
connect(nodeList, &NodeList::uuidChanged, this, &Application::updateWindowTitle);
|
||||
connect(nodeList, &NodeList::limitOfSilentDomainCheckInsReached, nodeList, &NodeList::reset);
|
||||
|
||||
// connect to appropriate slots on AccountManager
|
||||
AccountManager& accountManager = AccountManager::getInstance();
|
||||
|
|
|
@ -554,6 +554,78 @@ void renderCircle(glm::vec3 position, float radius, glm::vec3 surfaceNormal, int
|
|||
}
|
||||
|
||||
|
||||
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance) {
|
||||
glBegin(GL_POLYGON);
|
||||
|
||||
// left side
|
||||
glVertex2f(x, y + bevelDistance);
|
||||
glVertex2f(x, y + height - bevelDistance);
|
||||
|
||||
// top side
|
||||
glVertex2f(x + bevelDistance, y + height);
|
||||
glVertex2f(x + width - bevelDistance, y + height);
|
||||
|
||||
// right
|
||||
glVertex2f(x + width, y + height - bevelDistance);
|
||||
glVertex2f(x + width, y + bevelDistance);
|
||||
|
||||
// bottom
|
||||
glVertex2f(x + width - bevelDistance, y);
|
||||
glVertex2f(x +bevelDistance, y);
|
||||
|
||||
glEnd();
|
||||
}
|
||||
|
||||
void renderRoundedCornersRect(int x, int y, int width, int height, int radius, int numPointsCorner) {
|
||||
#define MAX_POINTS_CORNER 50
|
||||
// At least "2" is needed
|
||||
if (numPointsCorner <= 1) {
|
||||
return;
|
||||
}
|
||||
if (numPointsCorner > MAX_POINTS_CORNER) {
|
||||
numPointsCorner = MAX_POINTS_CORNER;
|
||||
}
|
||||
|
||||
// Precompute sin and cos for [0, pi/2) for the number of points (numPointCorner)
|
||||
double radiusTimesSin[MAX_POINTS_CORNER];
|
||||
double radiusTimesCos[MAX_POINTS_CORNER];
|
||||
int i = 0;
|
||||
for (int i = 0; i < numPointsCorner; i++) {
|
||||
double t = i * PIf / (2.0f * (numPointsCorner - 1));
|
||||
radiusTimesSin[i] = radius * sin(t);
|
||||
radiusTimesCos[i] = radius * cos(t);
|
||||
}
|
||||
|
||||
glm::dvec2 cornerCenter;
|
||||
glBegin(GL_POINTS);
|
||||
|
||||
// Top left corner
|
||||
cornerCenter = glm::vec2(x + radius, y + height - radius);
|
||||
for (i = 0; i < numPointsCorner; i++) {
|
||||
glVertex2d(cornerCenter.x - radiusTimesCos[i], cornerCenter.y + radiusTimesSin[i]);
|
||||
}
|
||||
|
||||
// Top rigth corner
|
||||
cornerCenter = glm::vec2(x + width - radius, y + height - radius);
|
||||
for (i = 0; i < numPointsCorner; i++) {
|
||||
glVertex2d(cornerCenter.x + radiusTimesSin[i], cornerCenter.y + radiusTimesCos[i]);
|
||||
}
|
||||
|
||||
// Bottom right
|
||||
cornerCenter = glm::vec2(x + width - radius, y + radius);
|
||||
for (i = 0; i < numPointsCorner; i++) {
|
||||
glVertex2d(cornerCenter.x + radiusTimesCos[i], cornerCenter.y - radiusTimesSin[i]);
|
||||
}
|
||||
|
||||
// Bottom left
|
||||
cornerCenter = glm::vec2(x + radius, y + radius);
|
||||
for (i = 0; i < numPointsCorner; i++) {
|
||||
glVertex2d(cornerCenter.x - radiusTimesSin[i], cornerCenter.y - radiusTimesCos[i]);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
|
||||
|
||||
void renderOrientationDirections(glm::vec3 position, const glm::quat& orientation, float size) {
|
||||
glm::vec3 pRight = position + orientation * IDENTITY_RIGHT * size;
|
||||
glm::vec3 pUp = position + orientation * IDENTITY_UP * size;
|
||||
|
|
|
@ -73,6 +73,8 @@ void renderOrientationDirections( glm::vec3 position, const glm::quat& orientati
|
|||
|
||||
void renderSphereOutline(glm::vec3 position, float radius, int numSides, glm::vec3 cameraPosition);
|
||||
void renderCircle(glm::vec3 position, float radius, glm::vec3 surfaceNormal, int numSides );
|
||||
void renderRoundedCornersRect(int x, int y, int width, int height, int radius, int numPointsCorner);
|
||||
void renderBevelCornersRect(int x, int y, int width, int height, int bevelDistance);
|
||||
|
||||
void runTimingTests();
|
||||
|
||||
|
|
|
@ -207,18 +207,23 @@ void Avatar::render() {
|
|||
renderBody();
|
||||
}
|
||||
|
||||
// render sphere when far away
|
||||
const float MAX_ANGLE = 10.f;
|
||||
// render voice intensity sphere for avatars that are farther away
|
||||
const float MAX_SPHERE_ANGLE = 10.f;
|
||||
const float MIN_SPHERE_ANGLE = 1.f;
|
||||
const float MIN_SPHERE_SIZE = 0.01;
|
||||
const float SPHERE_LOUDNESS_SCALING = 0.0005f;
|
||||
const float SPHERE_COLOR[] = { 0.5f, 0.8f, 0.8f };
|
||||
float height = getSkeletonHeight();
|
||||
glm::vec3 delta = height * (getHead()->getCameraOrientation() * IDENTITY_UP) / 2.f;
|
||||
float angle = abs(angleBetween(toTarget + delta, toTarget - delta));
|
||||
|
||||
if (angle < MAX_ANGLE) {
|
||||
glColor4f(0.5f, 0.8f, 0.8f, 1.f - angle / MAX_ANGLE);
|
||||
float sphereRadius = getHead()->getAverageLoudness() * SPHERE_LOUDNESS_SCALING;
|
||||
|
||||
if ((sphereRadius > MIN_SPHERE_SIZE) && (angle < MAX_SPHERE_ANGLE) && (angle > MIN_SPHERE_ANGLE)) {
|
||||
glColor4f(SPHERE_COLOR[0], SPHERE_COLOR[1], SPHERE_COLOR[2], 1.f - angle / MAX_SPHERE_ANGLE);
|
||||
glPushMatrix();
|
||||
glTranslatef(_position.x, _position.y, _position.z);
|
||||
glScalef(height / 2.f, height / 2.f, height / 2.f);
|
||||
glutSolidSphere(1.2f + getHead()->getAverageLoudness() * .0005f, 20, 20);
|
||||
glScalef(height, height, height);
|
||||
glutSolidSphere(sphereRadius, 15, 15);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
@ -424,16 +429,9 @@ void Avatar::renderDisplayName() {
|
|||
glPolygonOffset(1.0f, 1.0f);
|
||||
|
||||
glColor4f(0.2f, 0.2f, 0.2f, _displayNameAlpha * DISPLAYNAME_BACKGROUND_ALPHA / DISPLAYNAME_ALPHA);
|
||||
glBegin(GL_QUADS);
|
||||
glVertex2f(left, bottom);
|
||||
glVertex2f(right, bottom);
|
||||
glVertex2f(right, top);
|
||||
glVertex2f(left, top);
|
||||
glEnd();
|
||||
|
||||
|
||||
renderBevelCornersRect(left, bottom, right - left, top - bottom, 3);
|
||||
|
||||
glColor4f(0.93f, 0.93f, 0.93f, _displayNameAlpha);
|
||||
|
||||
QByteArray ba = _displayName.toLocal8Bit();
|
||||
const char* text = ba.data();
|
||||
|
||||
|
|
|
@ -44,13 +44,8 @@ void Sound::replyFinished(QNetworkReply* reply) {
|
|||
|
||||
QByteArray headerContentType = reply->rawHeader("Content-Type");
|
||||
|
||||
// RAW audio file encountered
|
||||
if (headerContentType == "application/octet-stream") {
|
||||
downSample(rawAudioByteArray);
|
||||
}
|
||||
|
||||
// WAV audio file encountered
|
||||
else if (headerContentType == "audio/x-wav"
|
||||
if (headerContentType == "audio/x-wav"
|
||||
|| headerContentType == "audio/wav"
|
||||
|| headerContentType == "audio/wave") {
|
||||
|
||||
|
@ -59,7 +54,8 @@ void Sound::replyFinished(QNetworkReply* reply) {
|
|||
interpretAsWav(rawAudioByteArray, outputAudioByteArray);
|
||||
downSample(outputAudioByteArray);
|
||||
} else {
|
||||
qDebug() << "Unknown audio file 'Content-Type'.";
|
||||
// Process as RAW file
|
||||
downSample(rawAudioByteArray);
|
||||
}
|
||||
} else {
|
||||
qDebug() << "Network reply without 'Content-Type'.";
|
||||
|
|
|
@ -11,6 +11,9 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#include <QtCore/QDataStream>
|
||||
#include <QtNetwork/QNetworkAccessManager>
|
||||
#include <QtNetwork/QNetworkReply>
|
||||
#include <QtNetwork/QNetworkRequest>
|
||||
|
||||
#include <NodeList.h>
|
||||
#include <PacketHeaders.h>
|
||||
|
@ -24,6 +27,8 @@ using namespace std;
|
|||
|
||||
static const float fingerVectorRadix = 4; // bits of precision when converting from float<->fixed
|
||||
|
||||
QNetworkAccessManager* AvatarData::networkAccessManager = NULL;
|
||||
|
||||
AvatarData::AvatarData() :
|
||||
NodeData(),
|
||||
_handPosition(0,0,0),
|
||||
|
@ -38,7 +43,8 @@ AvatarData::AvatarData() :
|
|||
_handData(NULL),
|
||||
_displayNameBoundingRect(),
|
||||
_displayNameTargetAlpha(0.0f),
|
||||
_displayNameAlpha(0.0f)
|
||||
_displayNameAlpha(0.0f),
|
||||
_billboard()
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -338,6 +344,28 @@ void AvatarData::setBillboard(const QByteArray& billboard) {
|
|||
qDebug() << "Changing billboard for avatar.";
|
||||
}
|
||||
|
||||
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.";
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarData::setBillboardFromNetworkReply() {
|
||||
QNetworkReply* networkReply = reinterpret_cast<QNetworkReply*>(sender());
|
||||
setBillboard(networkReply->readAll());
|
||||
}
|
||||
|
||||
void AvatarData::setClampedTargetScale(float targetScale) {
|
||||
|
||||
targetScale = glm::clamp(targetScale, MIN_AVATAR_SCALE, MAX_AVATAR_SCALE);
|
||||
|
@ -361,8 +389,10 @@ void AvatarData::sendIdentityPacket() {
|
|||
}
|
||||
|
||||
void AvatarData::sendBillboardPacket() {
|
||||
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
|
||||
billboardPacket.append(_billboard);
|
||||
|
||||
NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
|
||||
if (!_billboard.isEmpty()) {
|
||||
QByteArray billboardPacket = byteArrayWithPopulatedHeader(PacketTypeAvatarBillboard);
|
||||
billboardPacket.append(_billboard);
|
||||
|
||||
NodeList::getInstance()->broadcastToNodes(billboardPacket, NodeSet() << NodeType::AvatarMixer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,8 @@ enum KeyState {
|
|||
|
||||
const glm::vec3 vec3Zero(0.0f);
|
||||
|
||||
class QNetworkAccessManager;
|
||||
|
||||
class AvatarData : public NodeData {
|
||||
Q_OBJECT
|
||||
|
||||
|
@ -88,6 +90,7 @@ class AvatarData : public NodeData {
|
|||
|
||||
Q_PROPERTY(QString faceModelURL READ getFaceModelURLFromScript WRITE setFaceModelURLFromScript)
|
||||
Q_PROPERTY(QString skeletonModelURL READ getSkeletonModelURLFromScript WRITE setSkeletonModelURLFromScript)
|
||||
Q_PROPERTY(QString billboardURL READ getBillboardURL WRITE setBillboardFromURL)
|
||||
public:
|
||||
AvatarData();
|
||||
~AvatarData();
|
||||
|
@ -170,6 +173,9 @@ public:
|
|||
virtual void setBillboard(const QByteArray& billboard);
|
||||
const QByteArray& getBillboard() const { return _billboard; }
|
||||
|
||||
void setBillboardFromURL(const QString& billboardURL);
|
||||
const QString& getBillboardURL() { return _billboardURL; }
|
||||
|
||||
QString getFaceModelURLFromScript() const { return _faceModelURL.toString(); }
|
||||
void setFaceModelURLFromScript(const QString& faceModelString) { setFaceModelURL(faceModelString); }
|
||||
|
||||
|
@ -177,11 +183,13 @@ public:
|
|||
void setSkeletonModelURLFromScript(const QString& skeletonModelString) { setSkeletonModelURL(QUrl(skeletonModelString)); }
|
||||
|
||||
virtual float getBoundingRadius() const { return 1.f; }
|
||||
|
||||
static void setNetworkAccessManager(QNetworkAccessManager* sharedAccessManager) { networkAccessManager = sharedAccessManager; }
|
||||
|
||||
public slots:
|
||||
void sendIdentityPacket();
|
||||
void sendBillboardPacket();
|
||||
|
||||
void setBillboardFromNetworkReply();
|
||||
protected:
|
||||
glm::vec3 _position;
|
||||
glm::vec3 _handPosition;
|
||||
|
@ -217,6 +225,9 @@ protected:
|
|||
float _displayNameAlpha;
|
||||
|
||||
QByteArray _billboard;
|
||||
QString _billboardURL;
|
||||
|
||||
static QNetworkAccessManager* networkAccessManager;
|
||||
|
||||
private:
|
||||
// privatize the copy constructor and assignment operator so they cannot be called
|
||||
|
|
|
@ -45,6 +45,7 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, co
|
|||
AbstractControllerScriptingInterface* controllerScriptingInterface) :
|
||||
_isAvatar(false),
|
||||
_avatarIdentityTimer(NULL),
|
||||
_avatarBillboardTimer(NULL),
|
||||
_avatarData(NULL)
|
||||
{
|
||||
_scriptContents = scriptContents;
|
||||
|
@ -79,14 +80,17 @@ void ScriptEngine::setIsAvatar(bool isAvatar) {
|
|||
_isAvatar = isAvatar;
|
||||
|
||||
if (_isAvatar && !_avatarIdentityTimer) {
|
||||
// set up the avatar identity timer
|
||||
// set up the avatar timers
|
||||
_avatarIdentityTimer = new QTimer(this);
|
||||
_avatarBillboardTimer = new QTimer(this);
|
||||
|
||||
// connect our slot
|
||||
connect(_avatarIdentityTimer, &QTimer::timeout, this, &ScriptEngine::sendAvatarIdentityPacket);
|
||||
connect(_avatarBillboardTimer, &QTimer::timeout, this, &ScriptEngine::sendAvatarBillboardPacket);
|
||||
|
||||
// start the timer
|
||||
// start the timers
|
||||
_avatarIdentityTimer->start(AVATAR_IDENTITY_PACKET_SEND_INTERVAL_MSECS);
|
||||
_avatarBillboardTimer->start(AVATAR_BILLBOARD_PACKET_SEND_INTERVAL_MSECS);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -196,6 +200,12 @@ void ScriptEngine::sendAvatarIdentityPacket() {
|
|||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::sendAvatarBillboardPacket() {
|
||||
if (_isAvatar && _avatarData) {
|
||||
_avatarData->sendBillboardPacket();
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::run() {
|
||||
if (!_isInitialized) {
|
||||
init();
|
||||
|
|
|
@ -85,10 +85,12 @@ protected:
|
|||
QScriptEngine _engine;
|
||||
bool _isAvatar;
|
||||
QTimer* _avatarIdentityTimer;
|
||||
QTimer* _avatarBillboardTimer;
|
||||
QHash<QTimer*, QScriptValue> _timerFunctionMap;
|
||||
|
||||
private:
|
||||
void sendAvatarIdentityPacket();
|
||||
void sendAvatarBillboardPacket();
|
||||
|
||||
QObject* setupTimerWithInterval(const QScriptValue& function, int intervalMS, bool isSingleShot);
|
||||
void stopTimer(QTimer* timer);
|
||||
|
|
|
@ -549,6 +549,12 @@ void NodeList::sendDomainServerCheckIn() {
|
|||
sendSTUNRequest();
|
||||
}
|
||||
|
||||
if (_numNoReplyDomainCheckIns >= MAX_SILENT_DOMAIN_SERVER_CHECK_INS) {
|
||||
// we haven't heard back from DS in MAX_SILENT_DOMAIN_SERVER_CHECK_INS
|
||||
// so emit our signal that indicates that
|
||||
emit limitOfSilentDomainCheckInsReached();
|
||||
}
|
||||
|
||||
// increment the count of un-replied check-ins
|
||||
_numNoReplyDomainCheckIns++;
|
||||
} else if (AccountManager::getInstance().hasValidAccessToken()) {
|
||||
|
|
|
@ -132,6 +132,7 @@ signals:
|
|||
void uuidChanged(const QUuid& ownerUUID);
|
||||
void nodeAdded(SharedNodePointer);
|
||||
void nodeKilled(SharedNodePointer);
|
||||
void limitOfSilentDomainCheckInsReached();
|
||||
private slots:
|
||||
void domainServerAuthReply(const QJsonObject& jsonObject);
|
||||
private:
|
||||
|
|
|
@ -22,7 +22,7 @@ OAuthAccessToken::OAuthAccessToken() :
|
|||
OAuthAccessToken::OAuthAccessToken(const QJsonObject& jsonObject) :
|
||||
token(jsonObject["access_token"].toString()),
|
||||
refreshToken(jsonObject["refresh_token"].toString()),
|
||||
expiryTimestamp(QDateTime::currentMSecsSinceEpoch() + jsonObject["expires_in"].toDouble()),
|
||||
expiryTimestamp(QDateTime::currentMSecsSinceEpoch() + (jsonObject["expires_in"].toDouble() * 1000)),
|
||||
tokenType(jsonObject["token_type"].toString())
|
||||
{
|
||||
|
||||
|
|
Loading…
Reference in a new issue