Merge pull request #9 from birarda/entity-script-server

ability to query without frustum only for entities with server scripts
This commit is contained in:
Clément Brisset 2017-01-18 15:14:02 -08:00 committed by GitHub
commit 842692e99b
37 changed files with 309 additions and 184 deletions

View file

@ -316,8 +316,9 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
int truePacketsSent = 0;
int trueBytesSent = 0;
int packetsSentThisInterval = 0;
bool isFullScene = ((!viewFrustumChanged) && nodeData->getViewFrustumJustStoppedChanging())
|| nodeData->hasLodChanged();
bool isFullScene = !nodeData->getUsesFrustum()
|| ((!viewFrustumChanged) && nodeData->getViewFrustumJustStoppedChanging())
|| nodeData->hasLodChanged();
bool somethingToSend = true; // assume we have something
@ -432,7 +433,8 @@ int OctreeSendThread::packetDistributor(SharedNodePointer node, OctreeQueryNode*
boundaryLevelAdjust, octreeSizeScale,
nodeData->getLastTimeBagEmpty(),
isFullScene, &nodeData->stats, _myServer->getJurisdiction(),
&nodeData->extraEncodeData);
&nodeData->extraEncodeData,
nodeData);
nodeData->copyCurrentViewFrustum(params.viewFrustum);
if (viewFrustumChanged) {
nodeData->copyLastKnownViewFrustum(params.lastViewFrustum);

View file

@ -88,6 +88,15 @@ void EntityScriptServer::run() {
_entityViewer.setJurisdictionListener(entityScriptingInterface->getJurisdictionListener());
_entityViewer.init();
// setup the JSON filter that asks for entities with a non-default serverScripts property
QJsonObject queryJSONParameters;
static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts";
queryJSONParameters[SERVER_SCRIPTS_PROPERTY] = EntityQueryFilterSymbol::NonDefault;
// setup the JSON parameters so that OctreeQuery does not use a frustum and uses our JSON filter
_entityViewer.getOctreeQuery().setUsesFrustum(false);
_entityViewer.getOctreeQuery().setJSONParameters(queryJSONParameters);
entityScriptingInterface->setEntityTree(_entityViewer.getTree());

View file

@ -2233,3 +2233,30 @@ void EntityItem::globalizeProperties(EntityItemProperties& properties, const QSt
QUuid empty;
properties.setParentID(empty);
}
bool EntityItem::matchesJSONFilters(const QJsonObject& jsonFilters) const {
// The intention for the query JSON filter and this method is to be flexible to handle a variety of filters for
// ALL entity properties. Some work will need to be done to the property system so that it can be more flexible
// (to grab the value and default value of a property given the string representation of that property, for example)
// currently the only property filter we handle is '+' for serverScripts
// which means that we only handle a filtered query asking for entities where the serverScripts property is non-default
static const QString SERVER_SCRIPTS_PROPERTY = "serverScripts";
for (auto& property : jsonFilters.keys()) {
if (property == SERVER_SCRIPTS_PROPERTY && jsonFilters[property] == EntityQueryFilterSymbol::NonDefault) {
// check if this entity has a non-default value for serverScripts
if (_serverScripts != ENTITY_ITEM_DEFAULT_SERVER_SCRIPTS) {
return true;
} else {
return false;
}
}
}
// the json filter syntax did not match what we expected, return a match
return true;
}

View file

@ -125,7 +125,7 @@ public:
void markAsChangedOnServer() { _changedOnServer = usecTimestampNow(); }
quint64 getLastChangedOnServer() const { return _changedOnServer; }
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
virtual OctreeElement::AppendState appendEntityData(OctreePacketData* packetData, EncodeBitstreamParams& params,
@ -470,6 +470,8 @@ public:
QUuid getLastEditedBy() const { return _lastEditedBy; }
void setLastEditedBy(QUuid value) { _lastEditedBy = value; }
bool matchesJSONFilters(const QJsonObject& jsonFilters) const;
protected:

View file

@ -32,21 +32,21 @@ KeyLightPropertyGroup EntityItemProperties::_staticKeyLight;
EntityPropertyList PROP_LAST_ITEM = (EntityPropertyList)(PROP_AFTER_LAST_ITEM - 1);
EntityItemProperties::EntityItemProperties(EntityPropertyFlags desiredProperties) :
_id(UNKNOWN_ENTITY_ID),
_idSet(false),
_lastEdited(0),
_type(EntityTypes::Unknown),
_id(UNKNOWN_ENTITY_ID),
_idSet(false),
_lastEdited(0),
_type(EntityTypes::Unknown),
_localRenderAlpha(1.0f),
_localRenderAlpha(1.0f),
_localRenderAlphaChanged(false),
_localRenderAlphaChanged(false),
_defaultSettings(true),
_naturalDimensions(1.0f, 1.0f, 1.0f),
_naturalPosition(0.0f, 0.0f, 0.0f),
_desiredProperties(desiredProperties)
_defaultSettings(true),
_naturalDimensions(1.0f, 1.0f, 1.0f),
_naturalPosition(0.0f, 0.0f, 0.0f),
_desiredProperties(desiredProperties)
{
}
void EntityItemProperties::setSittingPoints(const QVector<SittingPoint>& sittingPoints) {
@ -920,8 +920,9 @@ QScriptValue EntityItemProperties::entityPropertyFlagsToScriptValue(QScriptEngin
static QHash<QString, EntityPropertyList> _propertyStringsToEnums;
void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue& object, EntityPropertyFlags& flags) {
static std::once_flag initMap;
std::call_once(initMap, [](){
ADD_PROPERTY_TO_MAP(PROP_VISIBLE, Visible, visible, bool);
ADD_PROPERTY_TO_MAP(PROP_POSITION, Position, position, glm::vec3);
@ -1020,22 +1021,22 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_PROPERTY_TO_MAP(PROP_X_P_NEIGHBOR_ID, XPNeighborID, xPNeighborID, EntityItemID);
ADD_PROPERTY_TO_MAP(PROP_Y_P_NEIGHBOR_ID, YPNeighborID, yPNeighborID, EntityItemID);
ADD_PROPERTY_TO_MAP(PROP_Z_P_NEIGHBOR_ID, ZPNeighborID, zPNeighborID, EntityItemID);
ADD_PROPERTY_TO_MAP(PROP_PARENT_ID, ParentID, parentID, QUuid);
ADD_PROPERTY_TO_MAP(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, uint16_t);
ADD_PROPERTY_TO_MAP(PROP_LOCAL_POSITION, LocalPosition, localPosition, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_LOCAL_ROTATION, LocalRotation, localRotation, glm::quat);
ADD_PROPERTY_TO_MAP(PROP_LOCAL_VELOCITY, LocalVelocity, localVelocity, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_LOCAL_ANGULAR_VELOCITY, LocalAngularVelocity, localAngularVelocity, glm::vec3);
ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS_SET, JointRotationsSet, jointRotationsSet, QVector<bool>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_ROTATIONS, JointRotations, jointRotations, QVector<glm::quat>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>);
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>);
ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
@ -1044,10 +1045,10 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FIRST_FRAME, Animation, animation, FirstFrame, firstFrame);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_LAST_FRAME, Animation, animation, LastFrame, lastFrame);
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_HOLD, Animation, animation, Hold, hold);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_COLOR, Skybox, skybox, Color, color);
ADD_GROUP_PROPERTY_TO_MAP(PROP_SKYBOX_URL, Skybox, skybox, URL, url);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_SUN_MODEL_ENABLED, Stage, stage, SunModelEnabled, sunModelEnabled);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LATITUDE, Stage, stage, Latitude, latitude);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_LONGITUDE, Stage, stage, Longitude, longitude);
@ -1055,15 +1056,15 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_DAY, Stage, stage, Day, day);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_HOUR, Stage, stage, Hour, hour);
ADD_GROUP_PROPERTY_TO_MAP(PROP_STAGE_AUTOMATIC_HOURDAY, Stage, stage, AutomaticHourDay, automaticHourDay);
ADD_PROPERTY_TO_MAP(PROP_FLYING_ALLOWED, FlyingAllowed, flyingAllowed, bool);
ADD_PROPERTY_TO_MAP(PROP_GHOSTING_ALLOWED, GhostingAllowed, ghostingAllowed, bool);
ADD_PROPERTY_TO_MAP(PROP_DPI, DPI, dpi, uint16_t);
// FIXME - these are not yet handled
//ADD_PROPERTY_TO_MAP(PROP_CREATED, Created, created, quint64);
});
if (object.isString()) {

View file

@ -14,7 +14,7 @@
#include <udt/PacketHeaders.h>
#include "../octree/OctreeQueryNode.h"
#include <OctreeQueryNode.h>
class EntityNodeData : public OctreeQueryNode {
public:
@ -22,9 +22,15 @@ public:
quint64 getLastDeletedEntitiesSentAt() const { return _lastDeletedEntitiesSentAt; }
void setLastDeletedEntitiesSentAt(quint64 sentAt) { _lastDeletedEntitiesSentAt = sentAt; }
// these can only be called from the OctreeSendThread for the given Node
void insertEntitySentLastFrame(const QUuid& entityID) { _entitiesSentLastFrame.insert(entityID); }
void removeEntitySentLastFrame(const QUuid& entityID) { _entitiesSentLastFrame.remove(entityID); }
bool sentEntityLastFrame(const QUuid& entityID) { return _entitiesSentLastFrame.contains(entityID); }
private:
quint64 _lastDeletedEntitiesSentAt { usecTimestampNow() };
QSet<QUuid> _entitiesSentLastFrame;
};
#endif // hifi_EntityNodeData_h

View file

@ -31,6 +31,9 @@ using ModelWeakPointer = std::weak_ptr<Model>;
class EntitySimulation;
namespace EntityQueryFilterSymbol {
static const QString NonDefault = "+";
}
class NewlyCreatedEntityHook {
public:

View file

@ -16,6 +16,7 @@
#include <OctreeUtils.h>
#include "EntitiesLogging.h"
#include "EntityNodeData.h"
#include "EntityItemProperties.h"
#include "EntityTree.h"
#include "EntityTreeElement.h"
@ -94,7 +95,7 @@ void EntityTreeElement::initializeExtraEncodeData(EncodeBitstreamParams& params)
bool EntityTreeElement::shouldIncludeChildData(int childIndex, EncodeBitstreamParams& params) const {
OctreeElementExtraEncodeData* extraEncodeData = params.extraEncodeData;
assert(extraEncodeData); // EntityTrees always require extra encode data on their encoding passes
if (extraEncodeData->contains(this)) {
EntityTreeElementExtraEncodeDataPointer entityTreeElementExtraEncodeData
= std::static_pointer_cast<EntityTreeElementExtraEncodeData>((*extraEncodeData)[this]);
@ -231,7 +232,7 @@ void EntityTreeElement::elementEncodeComplete(EncodeBitstreamParams& params) con
}
OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData* packetData,
EncodeBitstreamParams& params) const {
EncodeBitstreamParams& params) const {
OctreeElement::AppendState appendElementState = OctreeElement::COMPLETED; // assume the best...
@ -287,9 +288,41 @@ OctreeElement::AppendState EntityTreeElement::appendElementData(OctreePacketData
EntityItemPointer entity = _entityItems[i];
bool includeThisEntity = true;
if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastViewFrustumSent) {
if (!params.forceSendScene && entity->getLastChangedOnServer() < params.lastQuerySent) {
includeThisEntity = false;
}
auto entityNodeData = dynamic_cast<EntityNodeData*>(params.nodeData);
if (entityNodeData) {
// we have an EntityNodeData instance
// so we should assume that means we might have JSON filters to check
auto jsonFilters = entityNodeData->getJSONParameters();
if (!jsonFilters.isEmpty()) {
// if params include JSON filters, check if this entity matches
bool entityMatchesFilters = entity->matchesJSONFilters(jsonFilters);
if (entityMatchesFilters) {
// we should include this entity unless it has already been excluded
includeThisEntity = includeThisEntity && true;
// make sure this entity is in the set of entities sent last frame
entityNodeData->insertEntitySentLastFrame(entity->getID());
} else {
// we might include this entity if it matched in the previous frame
if (entityNodeData->sentEntityLastFrame(entity->getID())) {
includeThisEntity = includeThisEntity && true;
entityNodeData->removeEntitySentLastFrame(entity->getID());
} else {
includeThisEntity = false;
}
}
}
}
if (hadElementExtraData) {
includeThisEntity = includeThisEntity &&

View file

@ -127,7 +127,6 @@ public:
bool alreadyFullyEncoded(EncodeBitstreamParams& params) const;
/// Override to serialize the state of this element. This is used for persistance and for transmission across the network.
virtual OctreeElement::AppendState appendElementData(OctreePacketData* packetData,
EncodeBitstreamParams& params) const override;

View file

@ -174,7 +174,7 @@ int LightEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags LightEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_IS_SPOTLIGHT;

View file

@ -126,7 +126,7 @@ int LineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags LineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;

View file

@ -26,7 +26,7 @@ class LineEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -160,7 +160,7 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
return bytesRead;
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -29,7 +29,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -469,7 +469,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -170,7 +170,7 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_COLOR;

View file

@ -26,7 +26,7 @@ class PolyLineEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -179,7 +179,7 @@ int PolyVoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* dat
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags PolyVoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_VOXEL_VOLUME_SIZE;

View file

@ -26,7 +26,7 @@ class PolyVoxEntityItem : public EntityItem {
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -137,7 +137,7 @@ int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_SHAPE;

View file

@ -99,7 +99,7 @@ int TextEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags TextEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_TEXT;

View file

@ -30,7 +30,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -84,7 +84,7 @@ int WebEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, i
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags WebEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
requestedProperties += PROP_SOURCE_URL;

View file

@ -29,7 +29,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -133,7 +133,7 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
}
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);

View file

@ -30,7 +30,7 @@ public:
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
virtual bool setProperties(const EntityItemProperties& properties) override;
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
// TODO: eventually only include properties changed since the params.lastQuerySent time
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,

View file

@ -49,6 +49,8 @@ PacketVersion versionForPacketType(PacketType packetType) {
case PacketType::EntityEdit:
case PacketType::EntityData:
return VERSION_ENTITIES_SERVER_SCRIPTS;
case PacketType::EntityQuery:
return VERSION_ENTITIES_JSON_FILTER;
case PacketType::AvatarIdentity:
case PacketType::AvatarData:
case PacketType::BulkAvatarData:

View file

@ -199,6 +199,7 @@ const PacketVersion VERSION_WEB_ENTITIES_SUPPORT_DPI = 63;
const PacketVersion VERSION_ENTITIES_ARROW_ACTION = 64;
const PacketVersion VERSION_ENTITIES_LAST_EDITED_BY = 65;
const PacketVersion VERSION_ENTITIES_SERVER_SCRIPTS = 66;
const PacketVersion VERSION_ENTITIES_JSON_FILTER = 67;
enum class AssetServerPacketVersion: PacketVersion {
VegasCongestionControl = 19

View file

@ -1077,7 +1077,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// If we were previously in the view, then we normally will return out of here and stop recursing. But
// if we're in deltaView mode, and this element has changed since it was last sent, then we do
// need to send it.
if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))) {
if (wasInView && !(params.deltaView && element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))) {
if (params.stats) {
params.stats->skippedWasInView(element);
}
@ -1088,7 +1088,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// If we're not in delta sending mode, and we weren't asked to do a force send, and the voxel hasn't changed,
// then we can also bail early and save bits
if (!params.forceSendScene && !params.deltaView &&
!element->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE)) {
!element->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE)) {
if (params.stats) {
params.stats->skippedNoChange(element);
}
@ -1247,7 +1247,7 @@ int Octree::encodeTreeBitstreamRecursion(OctreeElementPointer element,
// need to send it.
if (!childWasInView ||
(params.deltaView &&
childElement->hasChangedSince(params.lastViewFrustumSent - CHANGE_FUDGE))){
childElement->hasChangedSince(params.lastQuerySent - CHANGE_FUDGE))){
childrenDataBits += (1 << (7 - originalIndex));
inViewWithColorCount++;

View file

@ -17,6 +17,7 @@
#include <QHash>
#include <QObject>
#include <QtCore/QJsonObject>
#include <shared/ReadWriteLockable.h>
#include <SimpleMovingAverage.h>
@ -68,7 +69,7 @@ class EncodeBitstreamParams {
public:
ViewFrustum viewFrustum;
ViewFrustum lastViewFrustum;
quint64 lastViewFrustumSent;
quint64 lastQuerySent;
int maxEncodeLevel;
int maxLevelReached;
bool includeExistsBits;
@ -81,6 +82,7 @@ public:
OctreeSceneStats* stats;
JurisdictionMap* jurisdictionMap;
OctreeElementExtraEncodeData* extraEncodeData;
NodeData* nodeData;
// output hints from the encode process
typedef enum {
@ -104,12 +106,13 @@ public:
bool useDeltaView = false,
int boundaryLevelAdjust = NO_BOUNDARY_ADJUST,
float octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE,
quint64 lastViewFrustumSent = IGNORE_LAST_SENT,
quint64 lastQuerySent = IGNORE_LAST_SENT,
bool forceSendScene = true,
OctreeSceneStats* stats = IGNORE_SCENE_STATS,
JurisdictionMap* jurisdictionMap = IGNORE_JURISDICTION_MAP,
OctreeElementExtraEncodeData* extraEncodeData = NULL) :
lastViewFrustumSent(lastViewFrustumSent),
OctreeElementExtraEncodeData* extraEncodeData = nullptr,
NodeData* nodeData = nullptr) :
lastQuerySent(lastQuerySent),
maxEncodeLevel(maxEncodeLevel),
maxLevelReached(0),
includeExistsBits(includeExistsBits),
@ -121,6 +124,7 @@ public:
stats(stats),
jurisdictionMap(jurisdictionMap),
extraEncodeData(extraEncodeData),
nodeData(nodeData),
stopReason(UNKNOWN)
{
lastViewFrustum.invalidate();

View file

@ -12,7 +12,7 @@
#ifndef hifi_OctreeConstants_h
#define hifi_OctreeConstants_h
#include <QtGlobal> // for quint64
#include <QtCore/QString> // for quint64/QString
#include <glm/glm.hpp>
const quint64 CHANGE_FUDGE = 1000 * 200; // useconds of fudge in determining if we want to resend changed voxels

View file

@ -108,7 +108,7 @@ public:
virtual bool isRendered() const { return getShouldRender(); }
virtual bool deleteApproved() const { return true; }
virtual bool canRayIntersect() const { return isLeaf(); }
/// \param center center of sphere in meters
/// \param radius radius of sphere in meters

View file

@ -36,6 +36,8 @@ public:
virtual void render(RenderArgs* renderArgs) override { /* swallow these */ }
void setJurisdictionListener(JurisdictionListener* jurisdictionListener) { _jurisdictionListener = jurisdictionListener; }
OctreeQuery& getOctreeQuery() { return _octreeQuery; }
static int parseOctreeStats(QSharedPointer<ReceivedMessage> message, SharedNodePointer sourceNode);
static void trackIncomingOctreePacket(const QByteArray& packet, const SharedNodePointer& sendingNode, bool wasStatsPacket);

View file

@ -9,13 +9,14 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include <QtCore/QJsonDocument>
#include <GLMHelpers.h>
#include <udt/PacketHeaders.h>
#include "OctreeConstants.h"
#include "OctreeQuery.h"
OctreeQuery::OctreeQuery() {
_maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
}
@ -23,35 +24,27 @@ OctreeQuery::OctreeQuery() {
int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
unsigned char* bufferStart = destinationBuffer;
// TODO: DRY this up to a shared method
// that can pack any type given the number of bytes
// and return the number of bytes to push the pointer
// back a boolean (cut to 1 byte) to designate if this query uses the sent view frustum
memcpy(destinationBuffer, &_usesFrustum, sizeof(_usesFrustum));
destinationBuffer += sizeof(_usesFrustum);
if (_usesFrustum) {
// TODO: DRY this up to a shared method
// that can pack any type given the number of bytes
// and return the number of bytes to push the pointer
// camera details
memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition));
destinationBuffer += sizeof(_cameraPosition);
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov);
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio);
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip);
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip);
memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition));
destinationBuffer += sizeof(_cameraEyeOffsetPosition);
}
// camera details
memcpy(destinationBuffer, &_cameraPosition, sizeof(_cameraPosition));
destinationBuffer += sizeof(_cameraPosition);
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _cameraOrientation);
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _cameraFov);
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _cameraAspectRatio);
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraNearClip);
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _cameraFarClip);
memcpy(destinationBuffer, &_cameraEyeOffsetPosition, sizeof(_cameraEyeOffsetPosition));
destinationBuffer += sizeof(_cameraEyeOffsetPosition);
// bitMask of less than byte wide items
unsigned char bitItems = 0;
// NOTE: we need to keep these here for new clients to talk to old servers. After we know that the clients and
// servers and clients have all been updated we could remove these bits. New servers will always force these
// features on old clients even if they don't ask for them. (which old clients will properly handle). New clients
// will always ask for these so that old servers will use these features.
setAtBit(bitItems, WANT_LOW_RES_MOVING_BIT);
setAtBit(bitItems, WANT_COLOR_AT_BIT);
setAtBit(bitItems, WANT_DELTA_AT_BIT);
setAtBit(bitItems, WANT_COMPRESSION);
*destinationBuffer++ = bitItems;
// desired Max Octree PPS
memcpy(destinationBuffer, &_maxQueryPPS, sizeof(_maxQueryPPS));
destinationBuffer += sizeof(_maxQueryPPS);
@ -67,6 +60,25 @@ int OctreeQuery::getBroadcastData(unsigned char* destinationBuffer) {
memcpy(destinationBuffer, &_cameraCenterRadius, sizeof(_cameraCenterRadius));
destinationBuffer += sizeof(_cameraCenterRadius);
// create a QByteArray that holds the binary representation of the JSON parameters
QByteArray binaryParametersDocument;
if (!_jsonParameters.isEmpty()) {
binaryParametersDocument = QJsonDocument(_jsonParameters).toBinaryData();
}
// write the size of the JSON parameters
uint16_t binaryParametersBytes = binaryParametersDocument.size();
memcpy(destinationBuffer, &binaryParametersBytes, sizeof(binaryParametersBytes));
destinationBuffer += sizeof(binaryParametersBytes);
// pack the binary JSON parameters
// NOTE: for now we assume that the filters that will be set are all small enough that we will not have a packet > MTU
if (binaryParametersDocument.size() > 0) {
memcpy(destinationBuffer, binaryParametersDocument.data(), binaryParametersBytes);
destinationBuffer += binaryParametersBytes;
}
return destinationBuffer - bufferStart;
}
@ -76,24 +88,22 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(message.getRawMessage());
const unsigned char* sourceBuffer = startPosition;
// camera details
memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));
sourceBuffer += sizeof(_cameraPosition);
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov);
sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio);
sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip);
sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip);
memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition));
sourceBuffer += sizeof(_cameraEyeOffsetPosition);
// optional feature flags
unsigned char bitItems = 0;
bitItems = (unsigned char)*sourceBuffer++;
// NOTE: we used to use these bits to set feature request items if we need to extend the protocol with optional features
// do it here with... wantFeature= oneAtBit(bitItems, WANT_FEATURE_BIT);
Q_UNUSED(bitItems);
// check if this query uses a view frustum
memcpy(&_usesFrustum, sourceBuffer, sizeof(_usesFrustum));
sourceBuffer += _usesFrustum;
if (_usesFrustum) {
// unpack camera details
memcpy(&_cameraPosition, sourceBuffer, sizeof(_cameraPosition));
sourceBuffer += sizeof(_cameraPosition);
sourceBuffer += unpackOrientationQuatFromBytes(sourceBuffer, _cameraOrientation);
sourceBuffer += unpackFloatAngleFromTwoByte((uint16_t*) sourceBuffer, &_cameraFov);
sourceBuffer += unpackFloatRatioFromTwoByte(sourceBuffer,_cameraAspectRatio);
sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraNearClip);
sourceBuffer += unpackClipValueFromTwoByte(sourceBuffer,_cameraFarClip);
memcpy(&_cameraEyeOffsetPosition, sourceBuffer, sizeof(_cameraEyeOffsetPosition));
sourceBuffer += sizeof(_cameraEyeOffsetPosition);
}
// desired Max Octree PPS
memcpy(&_maxQueryPPS, sourceBuffer, sizeof(_maxQueryPPS));
@ -106,13 +116,25 @@ int OctreeQuery::parseData(ReceivedMessage& message) {
// desired boundaryLevelAdjust
memcpy(&_boundaryLevelAdjust, sourceBuffer, sizeof(_boundaryLevelAdjust));
sourceBuffer += sizeof(_boundaryLevelAdjust);
auto bytesRead = sourceBuffer - startPosition;
auto bytesLeft = message.getSize() - bytesRead;
if (bytesLeft >= (int)sizeof(_cameraCenterRadius)) {
memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius));
sourceBuffer += sizeof(_cameraCenterRadius);
memcpy(&_cameraCenterRadius, sourceBuffer, sizeof(_cameraCenterRadius));
sourceBuffer += sizeof(_cameraCenterRadius);
// check if we have a packed JSON filter
uint16_t binaryParametersBytes;
memcpy(&binaryParametersBytes, sourceBuffer, sizeof(binaryParametersBytes));
sourceBuffer += sizeof(binaryParametersBytes);
if (binaryParametersBytes > 0) {
// unpack the binary JSON parameters
QByteArray binaryJSONParameters { binaryParametersBytes, 0 };
memcpy(binaryJSONParameters.data(), sourceBuffer, binaryParametersBytes);
sourceBuffer += binaryParametersBytes;
// grab the parameter object from the packed binary representation of JSON
_jsonParameters = QJsonDocument::fromBinaryData(binaryJSONParameters).object();
}
return sourceBuffer - startPosition;
}

View file

@ -31,14 +31,10 @@ typedef unsigned long long quint64;
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
#include <QtCore/QJsonObject>
#include <NodeData.h>
// First bitset
const int WANT_LOW_RES_MOVING_BIT = 0;
const int WANT_COLOR_AT_BIT = 1;
const int WANT_DELTA_AT_BIT = 2;
const int UNUSED_BIT_3 = 3; // unused... available for new feature
const int WANT_COMPRESSION = 4; // 5th bit
class OctreeQuery : public NodeData {
Q_OBJECT
@ -71,11 +67,18 @@ public:
void setCameraFarClip(float farClip) { _cameraFarClip = farClip; }
void setCameraEyeOffsetPosition(const glm::vec3& eyeOffsetPosition) { _cameraEyeOffsetPosition = eyeOffsetPosition; }
void setCameraCenterRadius(float radius) { _cameraCenterRadius = radius; }
// getters/setters for JSON filter
QJsonObject getJSONParameters() { return _jsonParameters; }
void setJSONParameters(const QJsonObject& jsonParameters) { _jsonParameters = jsonParameters; }
// related to Octree Sending strategies
int getMaxQueryPacketsPerSecond() const { return _maxQueryPPS; }
float getOctreeSizeScale() const { return _octreeElementSizeScale; }
int getBoundaryLevelAdjust() const { return _boundaryLevelAdjust; }
bool getUsesFrustum() { return _usesFrustum; }
void setUsesFrustum(bool usesFrustum) { _usesFrustum = usesFrustum; }
public slots:
void setMaxQueryPacketsPerSecond(int maxQueryPPS) { _maxQueryPPS = maxQueryPPS; }
@ -97,7 +100,11 @@ protected:
int _maxQueryPPS = DEFAULT_MAX_OCTREE_PPS;
float _octreeElementSizeScale = DEFAULT_OCTREE_SIZE_SCALE; /// used for LOD calculations
int _boundaryLevelAdjust = 0; /// used for LOD calculations
uint8_t _usesFrustum = true;
QJsonObject _jsonParameters;
private:
// privatize the copy constructor and assignment operator so they cannot be called
OctreeQuery(const OctreeQuery&);

View file

@ -1,6 +1,6 @@
//
// OctreeQueryNode.cpp
// assignment-client/src/octree
// libraries/octree/src
//
// Created by Stephen Birarda on 3/21/13.
// Copyright 2013 High Fidelity, Inc.
@ -18,7 +18,6 @@
#include <SharedUtil.h>
#include <UUID.h>
#include "OctreeSendThread.h"
void OctreeQueryNode::nodeKilled() {
_isShuttingDown = true;
@ -156,65 +155,71 @@ bool OctreeQueryNode::updateCurrentViewFrustum() {
if (_isShuttingDown) {
return false;
}
bool currentViewFrustumChanged = false;
ViewFrustum newestViewFrustum;
// get position and orientation details from the camera
newestViewFrustum.setPosition(getCameraPosition());
newestViewFrustum.setOrientation(getCameraOrientation());
newestViewFrustum.setCenterRadius(getCameraCenterRadius());
// Also make sure it's got the correct lens details from the camera
float originalFOV = getCameraFov();
float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
if (0.0f != getCameraAspectRatio() &&
0.0f != getCameraNearClip() &&
0.0f != getCameraFarClip() &&
getCameraNearClip() != getCameraFarClip()) {
newestViewFrustum.setProjection(glm::perspective(
glm::radians(wideFOV), // hack
getCameraAspectRatio(),
getCameraNearClip(),
getCameraFarClip()));
}
{ // if there has been a change, then recalculate
QMutexLocker viewLocker(&_viewMutex);
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate();
currentViewFrustumChanged = true;
}
}
// Also check for LOD changes from the client
if (_lodInitialized) {
if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = true;
}
if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
_lastClientOctreeSizeScale = getOctreeSizeScale();
_lodChanged = true;
}
if (_usesFrustum) {
// this client does not use a view frustum so the view frustum for this query has not changed
return false;
} else {
_lodInitialized = true;
_lastClientOctreeSizeScale = getOctreeSizeScale();
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = false;
bool currentViewFrustumChanged = false;
ViewFrustum newestViewFrustum;
// get position and orientation details from the camera
newestViewFrustum.setPosition(getCameraPosition());
newestViewFrustum.setOrientation(getCameraOrientation());
newestViewFrustum.setCenterRadius(getCameraCenterRadius());
// Also make sure it's got the correct lens details from the camera
float originalFOV = getCameraFov();
float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
if (0.0f != getCameraAspectRatio() &&
0.0f != getCameraNearClip() &&
0.0f != getCameraFarClip() &&
getCameraNearClip() != getCameraFarClip()) {
newestViewFrustum.setProjection(glm::perspective(
glm::radians(wideFOV), // hack
getCameraAspectRatio(),
getCameraNearClip(),
getCameraFarClip()));
}
{ // if there has been a change, then recalculate
QMutexLocker viewLocker(&_viewMutex);
if (!newestViewFrustum.isVerySimilar(_currentViewFrustum)) {
_currentViewFrustum = newestViewFrustum;
_currentViewFrustum.calculate();
currentViewFrustumChanged = true;
}
}
// Also check for LOD changes from the client
if (_lodInitialized) {
if (_lastClientBoundaryLevelAdjust != getBoundaryLevelAdjust()) {
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = true;
}
if (_lastClientOctreeSizeScale != getOctreeSizeScale()) {
_lastClientOctreeSizeScale = getOctreeSizeScale();
_lodChanged = true;
}
} else {
_lodInitialized = true;
_lastClientOctreeSizeScale = getOctreeSizeScale();
_lastClientBoundaryLevelAdjust = getBoundaryLevelAdjust();
_lodChanged = false;
}
// When we first detect that the view stopped changing, we record this.
// but we don't change it back to false until we've completely sent this
// scene.
if (_viewFrustumChanging && !currentViewFrustumChanged) {
_viewFrustumJustStoppedChanging = true;
}
_viewFrustumChanging = currentViewFrustumChanged;
return currentViewFrustumChanged;
}
// When we first detect that the view stopped changing, we record this.
// but we don't change it back to false until we've completely sent this
// scene.
if (_viewFrustumChanging && !currentViewFrustumChanged) {
_viewFrustumJustStoppedChanging = true;
}
_viewFrustumChanging = currentViewFrustumChanged;
return currentViewFrustumChanged;
}
void OctreeQueryNode::setViewSent(bool viewSent) {

View file

@ -1,6 +1,6 @@
//
// OctreeQueryNode.h
// assignment-client/src/octree
// libraries/octree/src
//
// Created by Brad Hefta-Gaub on 12/4/13.
// Copyright 2013 High Fidelity, Inc.
@ -15,11 +15,11 @@
#include <iostream>
#include <NodeData.h>
#include <OctreeConstants.h>
#include <OctreeElementBag.h>
#include <OctreePacketData.h>
#include <OctreeQuery.h>
#include <OctreeSceneStats.h>
#include "OctreeConstants.h"
#include "OctreeElementBag.h"
#include "OctreePacketData.h"
#include "OctreeQuery.h"
#include "OctreeSceneStats.h"
#include "SentPacketHistory.h"
#include <qqueue.h>