This commit is contained in:
ZappoMan 2013-10-26 16:37:58 -07:00
commit 0095259adf
14 changed files with 159 additions and 104 deletions

View file

@ -143,6 +143,8 @@ void Agent::run() {
int thisFrame = 0; int thisFrame = 0;
NodeList::getInstance()->startSilentNodeRemovalThread();
while (!_shouldStop) { while (!_shouldStop) {
// if we're not hearing from the domain-server we should stop running // if we're not hearing from the domain-server we should stop running
@ -159,26 +161,25 @@ void Agent::run() {
// find the audio-mixer in the NodeList so we can inject audio at it // find the audio-mixer in the NodeList so we can inject audio at it
Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER); Node* audioMixer = NodeList::getInstance()->soloNodeOfType(NODE_TYPE_AUDIO_MIXER);
if (audioMixer && audioMixer->getActiveSocket()) { if (audioMixer && audioMixer->getActiveSocket()) {
emit willSendAudioDataCallback(); emit willSendAudioDataCallback();
}
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) {
usleep(usecToSleep);
}
if (audioMixer && audioMixer->getActiveSocket() && scriptedAudioInjector.hasSamplesToInject()) {
// we have an audio mixer and samples to inject, send those off
scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getActiveSocket());
if (scriptedAudioInjector.hasSamplesToInject()) { // clear out the audio injector so that it doesn't re-send what we just sent
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow(); scriptedAudioInjector.clear();
if (usecToSleep > 0) { }
usleep(usecToSleep);
} if (audioMixer && !audioMixer->getActiveSocket()) {
scriptedAudioInjector.injectAudio(NodeList::getInstance()->getNodeSocket(), audioMixer->getActiveSocket());
// clear out the audio injector so that it doesn't re-send what we just sent
scriptedAudioInjector.clear();
}
} else if (audioMixer) {
int usecToSleep = usecTimestamp(&startTime) + (thisFrame++ * INJECT_INTERVAL_USECS) - usecTimestampNow();
if (usecToSleep > 0) {
usleep(usecToSleep);
}
// don't have an active socket for the audio-mixer, ping it now // don't have an active socket for the audio-mixer, ping it now
NodeList::getInstance()->pingPublicAndLocalSocketsForInactiveNode(audioMixer); NodeList::getInstance()->pingPublicAndLocalSocketsForInactiveNode(audioMixer);
} }
@ -202,9 +203,17 @@ void Agent::run() {
while (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes) while (NodeList::getInstance()->getNodeSocket()->receive((sockaddr*) &senderAddress, receivedData, &receivedBytes)
&& packetVersionMatch(receivedData)) { && packetVersionMatch(receivedData)) {
NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes); if (receivedData[0] == PACKET_TYPE_VOXEL_JURISDICTION) {
voxelScripter.getJurisdictionListener()->queueReceivedPacket((sockaddr&) senderAddress,
receivedData,
receivedBytes);
} else {
NodeList::getInstance()->processNodeData((sockaddr*) &senderAddress, receivedData, receivedBytes);
}
} }
} }
NodeList::getInstance()->stopSilentNodeRemovalThread();
} else { } else {
// error in curl_easy_perform // error in curl_easy_perform

View file

@ -8,6 +8,11 @@
#include "VoxelScriptingInterface.h" #include "VoxelScriptingInterface.h"
VoxelScriptingInterface::VoxelScriptingInterface() {
_jurisdictionListener.initialize(true);
_voxelPacketSender.setVoxelServerJurisdictions(_jurisdictionListener.getJurisdictions());
}
void VoxelScriptingInterface::queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails) { void VoxelScriptingInterface::queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails) {
_voxelPacketSender.queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails); _voxelPacketSender.queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails);
} }
@ -35,4 +40,4 @@ void VoxelScriptingInterface::queueVoxelDelete(float x, float y, float z, float
VoxelDetail deleteVoxelDetail = {x, y, z, scale, 0, 0, 0}; VoxelDetail deleteVoxelDetail = {x, y, z, scale, 0, 0, 0};
_voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_ERASE_VOXEL, 1, &deleteVoxelDetail); _voxelPacketSender.queueVoxelEditMessages(PACKET_TYPE_ERASE_VOXEL, 1, &deleteVoxelDetail);
} }

View file

@ -11,13 +11,17 @@
#include <QtCore/QObject> #include <QtCore/QObject>
#include <JurisdictionListener.h>
#include <VoxelEditPacketSender.h> #include <VoxelEditPacketSender.h>
/// handles scripting of voxel commands from JS passed to assigned clients /// handles scripting of voxel commands from JS passed to assigned clients
class VoxelScriptingInterface : public QObject { class VoxelScriptingInterface : public QObject {
Q_OBJECT Q_OBJECT
public: public:
VoxelScriptingInterface();
VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; } VoxelEditPacketSender* getVoxelPacketSender() { return &_voxelPacketSender; }
JurisdictionListener* getJurisdictionListener() { return &_jurisdictionListener; }
public slots: public slots:
/// queues the creation of a voxel which will be sent by calling process on the PacketSender /// queues the creation of a voxel which will be sent by calling process on the PacketSender
/// \param x the x-coordinate of the voxel (in VS space) /// \param x the x-coordinate of the voxel (in VS space)
@ -48,6 +52,7 @@ public slots:
private: private:
/// attached VoxelEditPacketSender that handles queuing and sending of packets to VS /// attached VoxelEditPacketSender that handles queuing and sending of packets to VS
VoxelEditPacketSender _voxelPacketSender; VoxelEditPacketSender _voxelPacketSender;
JurisdictionListener _jurisdictionListener;
void queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails); void queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails);
}; };

View file

@ -724,7 +724,7 @@ int DomainServer::run() {
Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment); Assignment* assignmentToDeploy = deployableAssignmentForRequest(requestAssignment);
if (assignmentToDeploy) { if (assignmentToDeploy) {
// give this assignment out, either the type matches or the requestor said they will take any // give this assignment out, either the type matches or the requestor said they will take any
int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT); int numHeaderBytes = populateTypeAndVersion(broadcastPacket, PACKET_TYPE_CREATE_ASSIGNMENT);
int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes); int numAssignmentBytes = assignmentToDeploy->packToBuffer(broadcastPacket + numHeaderBytes);

View file

@ -32,7 +32,7 @@ void main(void) {
normal = normalize(gl_ModelViewMatrix * normal); normal = normalize(gl_ModelViewMatrix * normal);
// pass along the vertex color // pass along the vertex color
gl_FrontColor = gl_Color; gl_FrontColor = vec4(1.0, 1.0, 1.0, 1.0);
// and the texture coordinates // and the texture coordinates
gl_TexCoord[0] = gl_MultiTexCoord0; gl_TexCoord[0] = gl_MultiTexCoord0;

View file

@ -194,7 +194,7 @@ Application::Application(int& argc, char** argv, timeval &startup_time) :
// call Menu getInstance static method to set up the menu // call Menu getInstance static method to set up the menu
_window->setMenuBar(Menu::getInstance()); _window->setMenuBar(Menu::getInstance());
// Check to see if the user passed in a command line option for loading a local // Check to see if the user passed in a command line option for loading a local
// Voxel File. // Voxel File.
_voxelsFilename = getCmdOption(argc, constArgv, "-i"); _voxelsFilename = getCmdOption(argc, constArgv, "-i");
@ -435,9 +435,8 @@ void Application::paintGL() {
_glowEffect.render(); _glowEffect.render();
if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) { if (Menu::getInstance()->isOptionChecked(MenuOption::Mirror)) {
glm::vec3 targetPosition = _myAvatar.getUprightHeadPosition(); _mirrorCamera.setDistance(0.3f);
_mirrorCamera.setDistance(0.2f); _mirrorCamera.setTargetPosition(_myAvatar.getHead().calculateAverageEyePosition());
_mirrorCamera.setTargetPosition(targetPosition);
_mirrorCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f))); _mirrorCamera.setTargetRotation(_myAvatar.getWorldAlignedOrientation() * glm::quat(glm::vec3(0.0f, PIf, 0.0f)));
_mirrorCamera.update(1.0f/_fps); _mirrorCamera.update(1.0f/_fps);
@ -534,6 +533,7 @@ void Application::resetProfile(const QString& username) {
// call the destructor on the old profile and construct a new one // call the destructor on the old profile and construct a new one
(&_profile)->~Profile(); (&_profile)->~Profile();
new (&_profile) Profile(username); new (&_profile) Profile(username);
updateWindowTitle();
} }
void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes, void Application::controlledBroadcastToNodes(unsigned char* broadcastData, size_t dataBytes,
@ -1674,7 +1674,7 @@ void Application::init() {
_mirrorCamera.setMode(CAMERA_MODE_MIRROR); _mirrorCamera.setMode(CAMERA_MODE_MIRROR);
_mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT); _mirrorCamera.setAspectRatio((float)MIRROR_VIEW_WIDTH / (float)MIRROR_VIEW_HEIGHT);
_mirrorCamera.setFieldOfView(70); _mirrorCamera.setFieldOfView(30);
_mirrorViewRect = QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT); _mirrorViewRect = QRect(MIRROR_VIEW_LEFT_PADDING, MIRROR_VIEW_TOP_PADDING, MIRROR_VIEW_WIDTH, MIRROR_VIEW_HEIGHT);
switchToResourcesParentIfRequired(); switchToResourcesParentIfRequired();
@ -3791,13 +3791,25 @@ void Application::attachNewHeadToNode(Node* newNode) {
} }
} }
void Application::updateWindowTitle(){
QString title = "";
QString username = _profile.getUsername();
if(!username.isEmpty()){
title += _profile.getUsername();
title += " @ ";
}
title += _profile.getLastDomain();
qDebug("Application title set to: %s.\n", title.toStdString().c_str());
_window->setWindowTitle(title);
}
void Application::domainChanged(QString domain) { void Application::domainChanged(QString domain) {
qDebug("Application title set to: %s.\n", domain.toStdString().c_str());
_window->setWindowTitle(domain);
// update the user's last domain in their Profile (which will propagate to data-server) // update the user's last domain in their Profile (which will propagate to data-server)
_profile.updateDomain(domain); _profile.updateDomain(domain);
updateWindowTitle();
// reset the environment so that we don't erroneously end up with multiple // reset the environment so that we don't erroneously end up with multiple
_environment.resetToDefault(); _environment.resetToDefault();
} }

View file

@ -109,6 +109,8 @@ public:
void touchEndEvent(QTouchEvent* event); void touchEndEvent(QTouchEvent* event);
void touchUpdateEvent(QTouchEvent* event); void touchUpdateEvent(QTouchEvent* event);
void updateWindowTitle();
void wheelEvent(QWheelEvent* event); void wheelEvent(QWheelEvent* event);
const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel); const glm::vec3 getMouseVoxelWorldCoordinates(const VoxelDetail _mouseVoxel);

View file

@ -532,6 +532,7 @@ void Menu::loadSettings(QSettings* settings) {
Application::getInstance()->getAvatar()->loadData(settings); Application::getInstance()->getAvatar()->loadData(settings);
Application::getInstance()->getSwatch()->loadData(settings); Application::getInstance()->getSwatch()->loadData(settings);
Application::getInstance()->getProfile()->loadData(settings); Application::getInstance()->getProfile()->loadData(settings);
Application::getInstance()->updateWindowTitle();
NodeList::getInstance()->loadData(settings); NodeList::getInstance()->loadData(settings);
} }

View file

@ -62,5 +62,8 @@ void FaceModel::maybeUpdateEyeRotation(const JointState& parentState, const FBXJ
glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f)); glm::vec3 front = glm::vec3(inverse * glm::vec4(_owningHead->getOrientation() * IDENTITY_FRONT, 0.0f));
glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() + glm::vec3 lookAt = glm::vec3(inverse * glm::vec4(_owningHead->getLookAtPosition() +
_owningHead->getSaccade(), 1.0f)); _owningHead->getSaccade(), 1.0f));
state.rotation = rotationBetween(front, lookAt) * joint.rotation; glm::quat between = rotationBetween(front, lookAt);
const float MAX_ANGLE = 22.5f;
state.rotation = glm::angleAxis(glm::clamp(glm::angle(between), -MAX_ANGLE, MAX_ANGLE), glm::axis(between)) *
joint.rotation;
} }

View file

@ -415,6 +415,16 @@ glm::vec3 parseVec3(const QString& string) {
return value; return value;
} }
QString processID(const QString& id) {
// Blender (at least) prepends a type to the ID, so strip it out
int index = id.indexOf("::");
return (index == -1) ? id : id.mid(index + 2);
}
QString getID(const QVariantList& properties, int index = 0) {
return processID(properties.at(index).toString());
}
const char* FACESHIFT_BLENDSHAPES[] = { const char* FACESHIFT_BLENDSHAPES[] = {
"EyeBlink_L", "EyeBlink_L",
"EyeBlink_R", "EyeBlink_R",
@ -469,7 +479,7 @@ const char* FACESHIFT_BLENDSHAPES[] = {
class FBXModel { class FBXModel {
public: public:
QByteArray name; QString name;
int parentIndex; int parentIndex;
@ -680,12 +690,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
QHash<QString, QString> bumpTextures; QHash<QString, QString> bumpTextures;
QVariantHash joints = mapping.value("joint").toHash(); QVariantHash joints = mapping.value("joint").toHash();
QByteArray jointEyeLeftName = joints.value("jointEyeLeft", "jointEyeLeft").toByteArray(); QString jointEyeLeftName = processID(joints.value("jointEyeLeft", "jointEyeLeft").toString());
QByteArray jointEyeRightName = joints.value("jointEyeRight", "jointEyeRight").toByteArray(); QString jointEyeRightName = processID(joints.value("jointEyeRight", "jointEyeRight").toString());
QByteArray jointNeckName = joints.value("jointNeck", "jointNeck").toByteArray(); QString jointNeckName = processID(joints.value("jointNeck", "jointNeck").toString());
QByteArray jointRootName = joints.value("jointRoot", "jointRoot").toByteArray(); QString jointRootName = processID(joints.value("jointRoot", "jointRoot").toString());
QByteArray jointLeanName = joints.value("jointLean", "jointLean").toByteArray(); QString jointLeanName = processID(joints.value("jointLean", "jointLean").toString());
QByteArray jointHeadName = joints.value("jointHead", "jointHead").toByteArray(); QString jointHeadName = processID(joints.value("jointHead", "jointHead").toString());
QString jointEyeLeftID; QString jointEyeLeftID;
QString jointEyeRightID; QString jointEyeRightID;
QString jointNeckID; QString jointNeckID;
@ -718,10 +728,10 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
foreach (const FBXNode& object, child.children) { foreach (const FBXNode& object, child.children) {
if (object.name == "Geometry") { if (object.name == "Geometry") {
if (object.properties.at(2) == "Mesh") { if (object.properties.at(2) == "Mesh") {
meshes.insert(object.properties.at(0).toString(), extractMesh(object)); meshes.insert(getID(object.properties), extractMesh(object));
} else { // object.properties.at(2) == "Shape" } else { // object.properties.at(2) == "Shape"
ExtractedBlendshape extracted = { object.properties.at(0).toString() }; ExtractedBlendshape extracted = { getID(object.properties) };
foreach (const FBXNode& data, object.children) { foreach (const FBXNode& data, object.children) {
if (data.name == "Indexes") { if (data.name == "Indexes") {
@ -740,31 +750,31 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
blendshapes.append(extracted); blendshapes.append(extracted);
} }
} else if (object.name == "Model") { } else if (object.name == "Model") {
QByteArray name; QString name;
if (object.properties.size() == 3) { if (object.properties.size() == 3) {
name = object.properties.at(1).toByteArray(); name = object.properties.at(1).toString();
name = name.left(name.indexOf('\0')); name = name.left(name.indexOf(QChar('\0')));
} else { } else {
name = object.properties.at(0).toByteArray(); name = getID(object.properties);
} }
if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") { if (name == jointEyeLeftName || name == "EyeL" || name == "joint_Leye") {
jointEyeLeftID = object.properties.at(0).toString(); jointEyeLeftID = getID(object.properties);
} else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye") { } else if (name == jointEyeRightName || name == "EyeR" || name == "joint_Reye") {
jointEyeRightID = object.properties.at(0).toString(); jointEyeRightID = getID(object.properties);
} else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck") { } else if (name == jointNeckName || name == "NeckRot" || name == "joint_neck") {
jointNeckID = object.properties.at(0).toString(); jointNeckID = getID(object.properties);
} else if (name == jointRootName) { } else if (name == jointRootName) {
jointRootID = object.properties.at(0).toString(); jointRootID = getID(object.properties);
} else if (name == jointLeanName) { } else if (name == jointLeanName) {
jointLeanID = object.properties.at(0).toString(); jointLeanID = getID(object.properties);
} else if (name == jointHeadName) { } else if (name == jointHeadName) {
jointHeadID = object.properties.at(0).toString(); jointHeadID = getID(object.properties);
} }
glm::vec3 translation; glm::vec3 translation;
glm::vec3 rotationOffset; glm::vec3 rotationOffset;
@ -817,7 +827,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} }
} else if (subobject.name == "Vertices") { } else if (subobject.name == "Vertices") {
// it's a mesh as well as a model // it's a mesh as well as a model
meshes.insert(object.properties.at(0).toString(), extractMesh(object)); meshes.insert(getID(object.properties), extractMesh(object));
} }
} }
// see FBX documentation, http://download.autodesk.com/us/fbx/20112/FBX_SDK_HELP/index.html // see FBX documentation, http://download.autodesk.com/us/fbx/20112/FBX_SDK_HELP/index.html
@ -828,7 +838,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
model.postRotation = glm::quat(glm::radians(postRotation)); model.postRotation = glm::quat(glm::radians(postRotation));
model.postTransform = glm::translate(-rotationPivot) * glm::translate(scalePivot) * model.postTransform = glm::translate(-rotationPivot) * glm::translate(scalePivot) *
glm::scale(scale) * glm::translate(-scalePivot); glm::scale(scale) * glm::translate(-scalePivot);
models.insert(object.properties.at(0).toString(), model); models.insert(getID(object.properties), model);
} else if (object.name == "Texture") { } else if (object.name == "Texture") {
foreach (const FBXNode& subobject, object.children) { foreach (const FBXNode& subobject, object.children) {
@ -836,7 +846,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
// trim off any path information // trim off any path information
QByteArray filename = subobject.properties.at(0).toByteArray(); QByteArray filename = subobject.properties.at(0).toByteArray();
filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1); filename = filename.mid(qMax(filename.lastIndexOf('\\'), filename.lastIndexOf('/')) + 1);
textureFilenames.insert(object.properties.at(0).toString(), filename); textureFilenames.insert(getID(object.properties), filename);
} }
} }
} else if (object.name == "Material") { } else if (object.name == "Material") {
@ -871,7 +881,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
} }
} }
} }
materials.insert(object.properties.at(0).toString(), material); materials.insert(getID(object.properties), material);
} else if (object.name == "Deformer") { } else if (object.name == "Deformer") {
if (object.properties.last() == "Cluster") { if (object.properties.last() == "Cluster") {
@ -888,7 +898,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
cluster.transformLink = createMat4(values); cluster.transformLink = createMat4(values);
} }
} }
clusters.insert(object.properties.at(0).toString(), cluster); clusters.insert(getID(object.properties), cluster);
} else if (object.properties.last() == "BlendShapeChannel") { } else if (object.properties.last() == "BlendShapeChannel") {
QByteArray name = object.properties.at(1).toByteArray(); QByteArray name = object.properties.at(1).toByteArray();
@ -897,8 +907,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
// try everything after the dot // try everything after the dot
name = name.mid(name.lastIndexOf('.') + 1); name = name.mid(name.lastIndexOf('.') + 1);
} }
blendshapeChannelIndices.insert(object.properties.at(0).toString(), blendshapeChannelIndices.insert(getID(object.properties), blendshapeIndices.value(name));
blendshapeIndices.value(name));
} }
} }
} }
@ -908,16 +917,14 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
if (connection.properties.at(0) == "OP") { if (connection.properties.at(0) == "OP") {
QByteArray type = connection.properties.at(3).toByteArray().toLower(); QByteArray type = connection.properties.at(3).toByteArray().toLower();
if (type.contains("diffuse")) { if (type.contains("diffuse")) {
diffuseTextures.insert(connection.properties.at(2).toString(), diffuseTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
connection.properties.at(1).toString());
} else if (type.contains("bump")) { } else if (type.contains("bump")) {
bumpTextures.insert(connection.properties.at(2).toString(), bumpTextures.insert(getID(connection.properties, 2), getID(connection.properties, 1));
connection.properties.at(1).toString());
} }
} }
parentMap.insert(connection.properties.at(1).toString(), connection.properties.at(2).toString()); parentMap.insert(getID(connection.properties, 1), getID(connection.properties, 2));
childMap.insert(connection.properties.at(2).toString(), connection.properties.at(1).toString()); childMap.insert(getID(connection.properties, 2), getID(connection.properties, 1));
} }
} }
} }
@ -1159,12 +1166,12 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
QVariantHash attachments = mapping.value("attach").toHash(); QVariantHash attachments = mapping.value("attach").toHash();
for (QVariantHash::const_iterator it = attachments.constBegin(); it != attachments.constEnd(); it++) { for (QVariantHash::const_iterator it = attachments.constBegin(); it != attachments.constEnd(); it++) {
FBXAttachment attachment; FBXAttachment attachment;
attachment.jointIndex = modelIDs.indexOf(it.key()); attachment.jointIndex = modelIDs.indexOf(processID(it.key()));
attachment.scale = glm::vec3(1.0f, 1.0f, 1.0f); attachment.scale = glm::vec3(1.0f, 1.0f, 1.0f);
QVariantList properties = it->toList(); QVariantList properties = it->toList();
if (properties.isEmpty()) { if (properties.isEmpty()) {
attachment.url = it->toUrl(); attachment.url = it->toString();
} else { } else {
attachment.url = properties.at(0).toString(); attachment.url = properties.at(0).toString();

View file

@ -90,6 +90,7 @@ Assignment::Assignment(const unsigned char* dataBuffer, int numBytes) :
if (dataBuffer[numBytesRead] != '\0') { if (dataBuffer[numBytesRead] != '\0') {
// read the pool from the data buffer // read the pool from the data buffer
setPool((const char*) dataBuffer + numBytesRead); setPool((const char*) dataBuffer + numBytesRead);
numBytesRead += strlen(_pool) + sizeof('\0');
} else { } else {
// skip past the null pool and null out our pool // skip past the null pool and null out our pool
setPool(NULL); setPool(NULL);
@ -192,7 +193,7 @@ int Assignment::packToBuffer(unsigned char* buffer) {
numPackedBytes += NUM_BYTES_RFC4122_UUID; numPackedBytes += NUM_BYTES_RFC4122_UUID;
} }
if (_pool) { if (hasPool()) {
// pack the pool for this assignment, it exists // pack the pool for this assignment, it exists
int numBytesNullTerminatedPool = strlen(_pool) + sizeof('\0'); int numBytesNullTerminatedPool = strlen(_pool) + sizeof('\0');
memcpy(buffer + numPackedBytes, _pool, numBytesNullTerminatedPool); memcpy(buffer + numPackedBytes, _pool, numBytesNullTerminatedPool);

View file

@ -492,10 +492,10 @@ void NodeList::sendDomainServerCheckIn() {
// check in packet has header, optional UUID, node type, port, IP, node types of interest, null termination // check in packet has header, optional UUID, node type, port, IP, node types of interest, null termination
int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) + int numPacketBytes = sizeof(PACKET_TYPE) + sizeof(PACKET_VERSION) + sizeof(NODE_TYPE) +
NUM_BYTES_RFC4122_UUID + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) + NUM_BYTES_RFC4122_UUID + (2 * (sizeof(uint16_t) + IP_ADDRESS_BYTES)) +
numBytesNodesOfInterest + sizeof(unsigned char); numBytesNodesOfInterest + sizeof(unsigned char);
unsigned char* checkInPacket = new unsigned char[numPacketBytes]; unsigned char checkInPacket[numPacketBytes];
unsigned char* packetPosition = checkInPacket; unsigned char* packetPosition = checkInPacket;
PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES))) PACKET_TYPE nodePacketType = (memchr(SOLO_NODE_TYPES, _ownerType, sizeof(SOLO_NODE_TYPES)))
@ -533,8 +533,6 @@ void NodeList::sendDomainServerCheckIn() {
_nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, checkInPacket, _nodeSocket.send(_domainIP.toString().toLocal8Bit().constData(), _domainPort, checkInPacket,
packetPosition - checkInPacket); packetPosition - checkInPacket);
delete[] checkInPacket; // clean up
const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5; const int NUM_DOMAIN_SERVER_CHECKINS_PER_STUN_REQUEST = 5;
static unsigned int numDomainCheckins = 0; static unsigned int numDomainCheckins = 0;

View file

@ -74,6 +74,10 @@ bool PacketSender::process() {
// we can determine how many packets we need to send per call to achieve our desired // we can determine how many packets we need to send per call to achieve our desired
// packets per second send rate. // packets per second send rate.
int callsPerSecond = USECS_PER_SECOND / averageCallTime; int callsPerSecond = USECS_PER_SECOND / averageCallTime;
// make sure our number of calls per second doesn't cause a divide by zero
callsPerSecond = glm::clamp(callsPerSecond, 1, _packetsPerSecond);
packetsPerCall = ceil(_packetsPerSecond / callsPerSecond); packetsPerCall = ceil(_packetsPerSecond / callsPerSecond);
// send at least one packet per call, if we have it // send at least one packet per call, if we have it

View file

@ -351,6 +351,7 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const {
int indexTwo = getNthBit(_childBitmask, 2); int indexTwo = getNthBit(_childBitmask, 2);
if (_childrenExternal) { if (_childrenExternal) {
//assert(_children.external);
if (indexOne == childIndex) { if (indexOne == childIndex) {
result = _children.external[0]; result = _children.external[0];
} else if (indexTwo == childIndex) { } else if (indexTwo == childIndex) {
@ -375,6 +376,7 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const {
int indexThree = getNthBit(_childBitmask, 3); int indexThree = getNthBit(_childBitmask, 3);
if (_childrenExternal) { if (_childrenExternal) {
//assert(_children.external);
if (indexOne == childIndex) { if (indexOne == childIndex) {
result = _children.external[0]; result = _children.external[0];
} else if (indexTwo == childIndex) { } else if (indexTwo == childIndex) {
@ -407,7 +409,12 @@ VoxelNode* VoxelNode::getChildAtIndex(int childIndex) const {
for (int ordinal = 1; ordinal <= childCount; ordinal++) { for (int ordinal = 1; ordinal <= childCount; ordinal++) {
int index = getNthBit(_childBitmask, ordinal); int index = getNthBit(_childBitmask, ordinal);
if (index == childIndex) { if (index == childIndex) {
result = _children.external[ordinal-1]; int externalIndex = ordinal-1;
if (externalIndex < childCount && externalIndex >= 0) {
result = _children.external[externalIndex];
} else {
qDebug("getChildAtIndex() attempt to access external client out of bounds externalIndex=%d <<<<<<<<<< WARNING!!! \n",externalIndex);
}
break; break;
} }
} }
@ -430,9 +437,11 @@ void VoxelNode::storeTwoChildren(VoxelNode* childOne, VoxelNode* childTwo) {
const int64_t minOffset = std::numeric_limits<int32_t>::min(); const int64_t minOffset = std::numeric_limits<int32_t>::min();
const int64_t maxOffset = std::numeric_limits<int32_t>::max(); const int64_t maxOffset = std::numeric_limits<int32_t>::max();
if (isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) { bool forceExternal = true;
if (!forceExternal && isBetween(offsetOne, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset)) {
// if previously external, then clean it up... // if previously external, then clean it up...
if (_childrenExternal) { if (_childrenExternal) {
//assert(_children.external);
const int previousChildCount = 2; const int previousChildCount = 2;
_externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*);
delete[] _children.external; delete[] _children.external;
@ -539,7 +548,9 @@ void VoxelNode::storeThreeChildren(VoxelNode* childOne, VoxelNode* childTwo, Vox
const int64_t minOffset = -1048576; // what can fit in 20 bits // std::numeric_limits<int16_t>::min(); const int64_t minOffset = -1048576; // what can fit in 20 bits // std::numeric_limits<int16_t>::min();
const int64_t maxOffset = 1048576; // what can fit in 20 bits // std::numeric_limits<int16_t>::max(); const int64_t maxOffset = 1048576; // what can fit in 20 bits // std::numeric_limits<int16_t>::max();
if (isBetween(offsetOne, maxOffset, minOffset) && bool forceExternal = true;
if (!forceExternal &&
isBetween(offsetOne, maxOffset, minOffset) &&
isBetween(offsetTwo, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset) &&
isBetween(offsetThree, maxOffset, minOffset)) { isBetween(offsetThree, maxOffset, minOffset)) {
// if previously external, then clean it up... // if previously external, then clean it up...
@ -601,7 +612,9 @@ void VoxelNode::checkStoreFourChildren(VoxelNode* childOne, VoxelNode* childTwo,
const int64_t minOffset = std::numeric_limits<int16_t>::min(); const int64_t minOffset = std::numeric_limits<int16_t>::min();
const int64_t maxOffset = std::numeric_limits<int16_t>::max(); const int64_t maxOffset = std::numeric_limits<int16_t>::max();
if (isBetween(offsetOne, maxOffset, minOffset) && bool forceExternal = true;
if (!forceExternal &&
isBetween(offsetOne, maxOffset, minOffset) &&
isBetween(offsetTwo, maxOffset, minOffset) && isBetween(offsetTwo, maxOffset, minOffset) &&
isBetween(offsetThree, maxOffset, minOffset) && isBetween(offsetThree, maxOffset, minOffset) &&
isBetween(offsetFour, maxOffset, minOffset) isBetween(offsetFour, maxOffset, minOffset)
@ -720,7 +733,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
storeTwoChildren(childOne, childTwo); storeTwoChildren(childOne, childTwo);
} else if (previousChildCount == 2 && newChildCount == 1) { } else if (previousChildCount == 2 && newChildCount == 1) {
// If we had 2 children, and we're removing one, then we know we can go down to single mode // If we had 2 children, and we're removing one, then we know we can go down to single mode
assert(child == NULL); // this is the only logical case //assert(child == NULL); // this is the only logical case
int indexTwo = getNthBit(previousChildMask, 2); int indexTwo = getNthBit(previousChildMask, 2);
bool keepChildOne = indexTwo == childIndex; bool keepChildOne = indexTwo == childIndex;
@ -743,31 +756,19 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
int indexOne = getNthBit(previousChildMask, 1); int indexOne = getNthBit(previousChildMask, 1);
bool replaceChildOne = indexOne == childIndex; bool replaceChildOne = indexOne == childIndex;
// If we previously had an external array, then just replace the right one... that's easy. // Get the existing two children out of their encoding...
if (_childrenExternal) { VoxelNode* childOne;
// technically, we could look to see if these are now in the offsets to handle be encoded, but VoxelNode* childTwo;
// we're going to go ahead and keep this as an array. retrieveTwoChildren(childOne, childTwo);
if (replaceChildOne) {
_children.external[0] = child;
} else {
_children.external[1] = child;
}
} else {
// If we were previously encoded as offsets, then we need to see if we can still encode as offsets
VoxelNode* childOne;
VoxelNode* childTwo;
if (replaceChildOne) {
childOne = child;
childTwo = (VoxelNode*)((uint8_t*)this + _children.offsetsTwoChildren[1]);
} else {
childOne = (VoxelNode*)((uint8_t*)this + _children.offsetsTwoChildren[0]);
childTwo = child;
}
_twoChildrenOffsetCount--; // will end up one or the other if (replaceChildOne) {
storeTwoChildren(childOne, childTwo); childOne = child;
} else {
childTwo = child;
} }
storeTwoChildren(childOne, childTwo);
} else if (previousChildCount == 2 && newChildCount == 3) { } else if (previousChildCount == 2 && newChildCount == 3) {
// If we had 2 children, and now have 3, then we know we are going to an external case... // If we had 2 children, and now have 3, then we know we are going to an external case...
@ -893,7 +894,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
_externalChildrenCount++; _externalChildrenCount++;
} else if (previousChildCount == 4 && newChildCount == 3) { } else if (previousChildCount == 4 && newChildCount == 3) {
// If we had 4 children, and now have 3, then we know we are going from an external case to a potential internal case // If we had 4 children, and now have 3, then we know we are going from an external case to a potential internal case
assert(_childrenExternal); //assert(_children.external && _childrenExternal && previousChildCount == 4);
// We need to determine which children we had, and which one we got rid of... // We need to determine which children we had, and which one we got rid of...
int indexOne = getNthBit(previousChildMask, 1); int indexOne = getNthBit(previousChildMask, 1);
@ -928,10 +929,11 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
_children.external = NULL; _children.external = NULL;
_externalChildrenCount--; _externalChildrenCount--;
_externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*);
storeThreeChildren(childOne, childTwo, childThree); storeThreeChildren(childOne, childTwo, childThree);
} else if (previousChildCount == newChildCount) { } else if (previousChildCount == newChildCount) {
//assert(_children.external && _childrenExternal && previousChildCount >= 4);
//assert(previousChildCount == newChildCount);
// 4 or more children, one item being replaced, we know we're stored externally, we just need to find the one // 4 or more children, one item being replaced, we know we're stored externally, we just need to find the one
// that needs to be replaced and replace it. // that needs to be replaced and replace it.
for (int ordinal = 1; ordinal <= 8; ordinal++) { for (int ordinal = 1; ordinal <= 8; ordinal++) {
@ -944,6 +946,10 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
} }
} }
} else if (previousChildCount < newChildCount) { } else if (previousChildCount < newChildCount) {
// Growing case... previous must be 4 or greater
//assert(_children.external && _childrenExternal && previousChildCount >= 4);
//assert(previousChildCount == newChildCount-1);
// 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert // 4 or more children, one item being added, we know we're stored externally, we just figure out where to insert
// this child pointer into our external list // this child pointer into our external list
VoxelNode** newExternalList = new VoxelNode*[newChildCount]; VoxelNode** newExternalList = new VoxelNode*[newChildCount];
@ -975,13 +981,16 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
} else if (previousChildCount > newChildCount) { } else if (previousChildCount > newChildCount) {
//assert(_children.external && _childrenExternal && previousChildCount >= 4);
//assert(previousChildCount == newChildCount+1);
// 4 or more children, one item being removed, we know we're stored externally, we just figure out which // 4 or more children, one item being removed, we know we're stored externally, we just figure out which
// item to remove from our external list // item to remove from our external list
VoxelNode** newExternalList = new VoxelNode*[newChildCount]; VoxelNode** newExternalList = new VoxelNode*[newChildCount];
for (int ordinal = 1; ordinal <= previousChildCount; ordinal++) { for (int ordinal = 1; ordinal <= previousChildCount; ordinal++) {
int index = getNthBit(previousChildMask, ordinal); int index = getNthBit(previousChildMask, ordinal);
assert(index != -1); //assert(index != -1);
if (index < childIndex) { if (index < childIndex) {
newExternalList[ordinal - 1] = _children.external[ordinal - 1]; newExternalList[ordinal - 1] = _children.external[ordinal - 1];
} else { } else {
@ -997,7 +1006,7 @@ void VoxelNode::setChildAtIndex(int childIndex, VoxelNode* child) {
_externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage -= previousChildCount * sizeof(VoxelNode*);
_externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*); _externalChildrenMemoryUsage += newChildCount * sizeof(VoxelNode*);
} else { } else {
assert(false); //assert(false);
qDebug("THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d\n",previousChildCount, newChildCount); qDebug("THIS SHOULD NOT HAPPEN previousChildCount == %d && newChildCount == %d\n",previousChildCount, newChildCount);
} }
@ -1024,7 +1033,6 @@ VoxelNode* VoxelNode::addChildAtIndex(int childIndex) {
childAt = new VoxelNode(childOctalCode(getOctalCode(), childIndex)); childAt = new VoxelNode(childOctalCode(getOctalCode(), childIndex));
childAt->setVoxelSystem(getVoxelSystem()); // our child is always part of our voxel system NULL ok childAt->setVoxelSystem(getVoxelSystem()); // our child is always part of our voxel system NULL ok
setChildAtIndex(childIndex, childAt); setChildAtIndex(childIndex, childAt);
_isDirty = true; _isDirty = true;