mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Merge pull request #489 from ey6es/master
Voxel URL sharing between avatars, tweak to rotation computations, fix for null replies.
This commit is contained in:
commit
b0cdb11ac3
8 changed files with 92 additions and 17 deletions
|
@ -105,6 +105,17 @@ int main(int argc, const char* argv[]) {
|
|||
|
||||
agentList->getAgentSocket()->send(agentAddress, broadcastPacket, currentBufferPosition - broadcastPacket);
|
||||
|
||||
break;
|
||||
case PACKET_HEADER_AVATAR_VOXEL_URL:
|
||||
// grab the agent ID from the packet
|
||||
unpackAgentId(packetData + 1, &agentID);
|
||||
|
||||
// let everyone else know about the update
|
||||
for (AgentList::iterator agent = agentList->begin(); agent != agentList->end(); agent++) {
|
||||
if (agent->getActiveSocket() && agent->getAgentID() != agentID) {
|
||||
agentList->getAgentSocket()->send(agent->getActiveSocket(), packetData, receivedBytes);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case PACKET_HEADER_DOMAIN:
|
||||
// ignore the DS packet, for now agents are added only when they communicate directly with us
|
||||
|
|
|
@ -983,6 +983,44 @@ void Application::terminate() {
|
|||
}
|
||||
}
|
||||
|
||||
static void sendAvatarVoxelURLMessage(const QUrl& url) {
|
||||
uint16_t ownerID = AgentList::getInstance()->getOwnerID();
|
||||
if (ownerID == UNKNOWN_AGENT_ID) {
|
||||
return; // we don't yet know who we are
|
||||
}
|
||||
QByteArray message;
|
||||
message.append(PACKET_HEADER_AVATAR_VOXEL_URL);
|
||||
message.append((const char*)&ownerID, sizeof(ownerID));
|
||||
message.append(url.toEncoded());
|
||||
|
||||
AgentList::getInstance()->broadcastToAgents((unsigned char*)message.data(), message.size(), &AGENT_TYPE_AVATAR_MIXER, 1);
|
||||
}
|
||||
|
||||
static void processAvatarVoxelURLMessage(unsigned char *packetData, size_t dataBytes) {
|
||||
// skip the header
|
||||
packetData++;
|
||||
dataBytes--;
|
||||
|
||||
// read the agent id
|
||||
uint16_t agentID = *(uint16_t*)packetData;
|
||||
packetData += sizeof(agentID);
|
||||
dataBytes -= sizeof(agentID);
|
||||
|
||||
// make sure the agent exists
|
||||
Agent* agent = AgentList::getInstance()->agentWithID(agentID);
|
||||
if (!agent || !agent->getLinkedData()) {
|
||||
return;
|
||||
}
|
||||
Avatar* avatar = static_cast<Avatar*>(agent->getLinkedData());
|
||||
if (!avatar->isInitialized()) {
|
||||
return; // wait until initialized
|
||||
}
|
||||
QUrl url = QUrl::fromEncoded(QByteArray((char*)packetData, dataBytes));
|
||||
|
||||
// invoke the set URL function on the simulate/render thread
|
||||
QMetaObject::invokeMethod(avatar->getVoxels(), "setVoxelURL", Q_ARG(QUrl, url));
|
||||
}
|
||||
|
||||
void Application::editPreferences() {
|
||||
QDialog dialog(_glWidget);
|
||||
dialog.setWindowTitle("Interface Preferences");
|
||||
|
@ -1006,7 +1044,8 @@ void Application::editPreferences() {
|
|||
}
|
||||
QUrl url(avatarURL->text());
|
||||
_settings->setValue("avatarURL", url);
|
||||
_myAvatar.getVoxels()->loadVoxelsFromURL(url);
|
||||
_myAvatar.getVoxels()->setVoxelURL(url);
|
||||
sendAvatarVoxelURLMessage(url);
|
||||
}
|
||||
|
||||
void Application::pair() {
|
||||
|
@ -1507,7 +1546,9 @@ void Application::init() {
|
|||
_myCamera.setModeShiftRate(1.0f);
|
||||
_myAvatar.setDisplayingLookatVectors(false);
|
||||
|
||||
_myAvatar.getVoxels()->loadVoxelsFromURL(_settings->value("avatarURL").toUrl());
|
||||
QUrl avatarURL = _settings->value("avatarURL").toUrl();
|
||||
_myAvatar.getVoxels()->setVoxelURL(avatarURL);
|
||||
sendAvatarVoxelURLMessage(avatarURL);
|
||||
|
||||
QCursor::setPos(_headMouseX, _headMouseY);
|
||||
|
||||
|
@ -1599,6 +1640,12 @@ void Application::updateAvatar(float deltaTime) {
|
|||
|
||||
const char broadcastReceivers[2] = {AGENT_TYPE_VOXEL, AGENT_TYPE_AVATAR_MIXER};
|
||||
AgentList::getInstance()->broadcastToAgents(broadcastString, endOfBroadcastStringWrite - broadcastString, broadcastReceivers, sizeof(broadcastReceivers));
|
||||
|
||||
// once in a while, send my voxel url
|
||||
const float AVATAR_VOXEL_URL_SEND_INTERVAL = 1.0f; // seconds
|
||||
if (shouldDo(AVATAR_VOXEL_URL_SEND_INTERVAL, deltaTime)) {
|
||||
sendAvatarVoxelURLMessage(_myAvatar.getVoxels()->getVoxelURL());
|
||||
}
|
||||
}
|
||||
|
||||
// If I'm in paint mode, send a voxel out to VOXEL server agents.
|
||||
|
@ -2435,6 +2482,9 @@ void* Application::networkReceive(void* args) {
|
|||
app->_incomingPacket,
|
||||
bytesReceived);
|
||||
break;
|
||||
case PACKET_HEADER_AVATAR_VOXEL_URL:
|
||||
processAvatarVoxelURLMessage(app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
default:
|
||||
AgentList::getInstance()->processAgentData(&senderAddress, app->_incomingPacket, bytesReceived);
|
||||
break;
|
||||
|
|
|
@ -1082,7 +1082,9 @@ void Avatar::updateBodyBalls(float deltaTime) {
|
|||
if (_skeleton.joint[b].parent == AVATAR_JOINT_NULL || length < SMALL_SPRING_LENGTH) {
|
||||
_bodyBall[b].rotation = orientation * _skeleton.joint[_bodyBall[b].parentJoint].absoluteBindPoseRotation;
|
||||
} else {
|
||||
_bodyBall[b].rotation = rotationBetween(jointDirection, springVector) * orientation;
|
||||
glm::vec3 parentDirection = _bodyBall[ _skeleton.joint[b].parent ].rotation * JOINT_DIRECTION;
|
||||
_bodyBall[b].rotation = rotationBetween(parentDirection, springVector) *
|
||||
_bodyBall[ _skeleton.joint[b].parent ].rotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include <cstring>
|
||||
|
||||
#include <QNetworkReply>
|
||||
#include <QUrl>
|
||||
|
||||
#include <GeometryUtil.h>
|
||||
|
||||
|
@ -24,6 +23,9 @@ const int BONE_ELEMENTS_PER_VOXEL = BONE_ELEMENTS_PER_VERTEX * VERTICES_PER_VOXE
|
|||
AvatarVoxelSystem::AvatarVoxelSystem(Avatar* avatar) :
|
||||
VoxelSystem(AVATAR_TREE_SCALE, MAX_VOXELS_PER_AVATAR),
|
||||
_avatar(avatar), _voxelReply(0) {
|
||||
|
||||
// we may have been created in the network thread, but we live in the main thread
|
||||
moveToThread(Application::getInstance()->thread());
|
||||
}
|
||||
|
||||
AvatarVoxelSystem::~AvatarVoxelSystem() {
|
||||
|
@ -75,14 +77,23 @@ void AvatarVoxelSystem::removeOutOfView() {
|
|||
// no-op for now
|
||||
}
|
||||
|
||||
void AvatarVoxelSystem::loadVoxelsFromURL(const QUrl& url) {
|
||||
void AvatarVoxelSystem::setVoxelURL(const QUrl& url) {
|
||||
// don't restart the download if it's the same URL
|
||||
if (_voxelURL == url) {
|
||||
return;
|
||||
}
|
||||
|
||||
// cancel any current download
|
||||
if (_voxelReply != 0) {
|
||||
delete _voxelReply;
|
||||
_voxelReply = 0;
|
||||
}
|
||||
|
||||
killLocalVoxels();
|
||||
|
||||
// remember the URL
|
||||
_voxelURL = url;
|
||||
|
||||
// handle "file://" urls...
|
||||
if (url.isLocalFile()) {
|
||||
QString pathString = url.path();
|
||||
|
@ -196,17 +207,11 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64
|
|||
return;
|
||||
}
|
||||
|
||||
// XXXBHG - I don't know why this can happen, but when I was testing this, I used a dropbox URL
|
||||
// and it resulted in a case where the bytesTotal == bytesReceived, but the _voxelReply was NULL
|
||||
// which needless to say caused crashes below. I've added this quick guard to protect against
|
||||
// this case, but it probably should be investigated.
|
||||
if (!_voxelReply) {
|
||||
return;
|
||||
}
|
||||
|
||||
QByteArray entirety = _voxelReply->readAll();
|
||||
_voxelReply->disconnect(this);
|
||||
_voxelReply->deleteLater();
|
||||
_voxelReply = 0;
|
||||
|
||||
_tree->readBitstreamToTree((unsigned char*)entirety.data(), entirety.size(), WANT_COLOR, NO_EXISTS_BITS);
|
||||
setupNewVoxelsForDrawing();
|
||||
}
|
||||
|
@ -214,6 +219,7 @@ void AvatarVoxelSystem::handleVoxelDownloadProgress(qint64 bytesReceived, qint64
|
|||
void AvatarVoxelSystem::handleVoxelReplyError() {
|
||||
printLog("%s\n", _voxelReply->errorString().toAscii().constData());
|
||||
|
||||
_voxelReply->disconnect(this);
|
||||
_voxelReply->deleteLater();
|
||||
_voxelReply = 0;
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#define __interface__AvatarVoxelSystem__
|
||||
|
||||
#include <QObject>
|
||||
#include <QUrl>
|
||||
|
||||
#include "VoxelSystem.h"
|
||||
|
||||
|
@ -17,7 +18,6 @@ const int BONE_ELEMENTS_PER_VERTEX = 4;
|
|||
typedef GLubyte BoneIndices[BONE_ELEMENTS_PER_VERTEX];
|
||||
|
||||
class QNetworkReply;
|
||||
class QUrl;
|
||||
|
||||
class Avatar;
|
||||
|
||||
|
@ -33,7 +33,8 @@ public:
|
|||
|
||||
virtual void removeOutOfView();
|
||||
|
||||
void loadVoxelsFromURL(const QUrl& url);
|
||||
Q_INVOKABLE void setVoxelURL(const QUrl& url);
|
||||
const QUrl& getVoxelURL() const { return _voxelURL; }
|
||||
|
||||
protected:
|
||||
|
||||
|
@ -55,6 +56,8 @@ private:
|
|||
|
||||
Avatar* _avatar;
|
||||
|
||||
QUrl _voxelURL;
|
||||
|
||||
GLubyte* _readBoneIndicesArray;
|
||||
GLfloat* _readBoneWeightsArray;
|
||||
GLubyte* _writeBoneIndicesArray;
|
||||
|
|
|
@ -118,7 +118,9 @@ void Skeleton::initialize() {
|
|||
} else {
|
||||
joint[b].absoluteBindPosePosition = joint[ joint[b].parent ].absoluteBindPosePosition +
|
||||
joint[b].bindPosePosition;
|
||||
joint[b].absoluteBindPoseRotation = rotationBetween(JOINT_DIRECTION, joint[b].bindPosePosition);
|
||||
glm::vec3 parentDirection = joint[ joint[b].parent ].absoluteBindPoseRotation * JOINT_DIRECTION;
|
||||
joint[b].absoluteBindPoseRotation = rotationBetween(parentDirection, joint[b].bindPosePosition) *
|
||||
joint[ joint[b].parent ].absoluteBindPoseRotation;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,7 +42,7 @@ enum AvatarJointID
|
|||
NUM_AVATAR_JOINTS
|
||||
};
|
||||
|
||||
const glm::vec3 JOINT_DIRECTION = glm::vec3(1.0f, 0.0f, 0.0f);
|
||||
const glm::vec3 JOINT_DIRECTION = glm::vec3(0.0f, 1.0f, 0.0f);
|
||||
|
||||
class Skeleton {
|
||||
public:
|
||||
|
|
|
@ -27,6 +27,7 @@ const PACKET_HEADER PACKET_HEADER_ERASE_VOXEL = 'E';
|
|||
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA = 'V';
|
||||
const PACKET_HEADER PACKET_HEADER_VOXEL_DATA_MONOCHROME = 'v';
|
||||
const PACKET_HEADER PACKET_HEADER_BULK_AVATAR_DATA = 'X';
|
||||
const PACKET_HEADER PACKET_HEADER_AVATAR_VOXEL_URL = 'U';
|
||||
const PACKET_HEADER PACKET_HEADER_TRANSMITTER_DATA_V2 = 'T';
|
||||
const PACKET_HEADER PACKET_HEADER_ENVIRONMENT_DATA = 'e';
|
||||
const PACKET_HEADER PACKET_HEADER_DOMAIN_LIST_REQUEST = 'L';
|
||||
|
|
Loading…
Reference in a new issue