mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-25 17:14:59 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into rightClickMenu
This commit is contained in:
commit
eb598bd3d3
5 changed files with 162 additions and 52 deletions
|
@ -18,17 +18,13 @@
|
|||
|
||||
class EntityNodeData : public OctreeQueryNode {
|
||||
public:
|
||||
EntityNodeData() :
|
||||
OctreeQueryNode(),
|
||||
_lastDeletedEntitiesSentAt(0) { }
|
||||
|
||||
virtual PacketType getMyPacketType() const { return PacketType::EntityData; }
|
||||
|
||||
quint64 getLastDeletedEntitiesSentAt() const { return _lastDeletedEntitiesSentAt; }
|
||||
void setLastDeletedEntitiesSentAt(quint64 sentAt) { _lastDeletedEntitiesSentAt = sentAt; }
|
||||
|
||||
private:
|
||||
quint64 _lastDeletedEntitiesSentAt;
|
||||
quint64 _lastDeletedEntitiesSentAt { usecTimestampNow() };
|
||||
};
|
||||
|
||||
#endif // hifi_EntityNodeData_h
|
||||
|
|
|
@ -82,9 +82,15 @@ bool EntityServer::hasSpecialPacketsToSend(const SharedNodePointer& node) {
|
|||
EntityNodeData* nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
|
||||
if (nodeData) {
|
||||
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
|
||||
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
shouldSendDeletedEntities = tree->hasEntitiesDeletedSince(deletedEntitiesSentAt);
|
||||
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
if (shouldSendDeletedEntities) {
|
||||
int elapsed = usecTimestampNow() - deletedEntitiesSentAt;
|
||||
qDebug() << "shouldSendDeletedEntities to node:" << node->getUUID() << "deletedEntitiesSentAt:" << deletedEntitiesSentAt << "elapsed:" << elapsed;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
return shouldSendDeletedEntities;
|
||||
|
@ -97,7 +103,6 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
|
|||
if (nodeData) {
|
||||
quint64 deletedEntitiesSentAt = nodeData->getLastDeletedEntitiesSentAt();
|
||||
quint64 deletePacketSentAt = usecTimestampNow();
|
||||
|
||||
EntityTreePointer tree = std::static_pointer_cast<EntityTree>(_tree);
|
||||
bool hasMoreToSend = true;
|
||||
|
||||
|
@ -118,6 +123,13 @@ int EntityServer::sendSpecialPackets(const SharedNodePointer& node, OctreeQueryN
|
|||
nodeData->setLastDeletedEntitiesSentAt(deletePacketSentAt);
|
||||
}
|
||||
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
if (packetsSent > 0) {
|
||||
qDebug() << "EntityServer::sendSpecialPackets() sent " << packetsSent << "special packets of "
|
||||
<< totalBytes << " total bytes to node:" << node->getUUID();
|
||||
}
|
||||
#endif
|
||||
|
||||
// TODO: caller is expecting a packetLength, what if we send more than one packet??
|
||||
return totalBytes;
|
||||
}
|
||||
|
@ -127,7 +139,6 @@ void EntityServer::pruneDeletedEntities() {
|
|||
if (tree->hasAnyDeletedEntities()) {
|
||||
|
||||
quint64 earliestLastDeletedEntitiesSent = usecTimestampNow() + 1; // in the future
|
||||
|
||||
DependencyManager::get<NodeList>()->eachNode([&earliestLastDeletedEntitiesSent](const SharedNodePointer& node) {
|
||||
if (node->getLinkedData()) {
|
||||
EntityNodeData* nodeData = static_cast<EntityNodeData*>(node->getLinkedData());
|
||||
|
@ -137,7 +148,6 @@ void EntityServer::pruneDeletedEntities() {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
tree->forgetEntitiesDeletedBefore(earliestLastDeletedEntitiesSent);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -570,7 +570,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
|||
}
|
||||
|
||||
|
||||
if (somethingToSend) {
|
||||
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
||||
qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval
|
||||
<< " maxPacketsPerInterval = " << maxPacketsPerInterval
|
||||
<< " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval;
|
||||
|
|
73
examples/example/avatarcontrol/handControlledHead.js
Normal file
73
examples/example/avatarcontrol/handControlledHead.js
Normal file
|
@ -0,0 +1,73 @@
|
|||
//
|
||||
// handControlledHead.js
|
||||
// examples
|
||||
//
|
||||
// Created by Alessandro Signa on 10/11/15.
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// This script allows you to look around, driving the rotation of the avatar's head by the right hand orientation.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
|
||||
const YAW_MULTIPLIER = 20000;
|
||||
const PITCH_MULTIPLIER = 15000;
|
||||
const EPSILON = 0.001;
|
||||
var firstPress = true;
|
||||
var handPreviousVerticalRotation = 0.0;
|
||||
var handCurrentVerticalRotation = 0.0;
|
||||
var handPreviousHorizontalRotation = 0.0;
|
||||
var handCurrentHorizontalRotation = 0.0;
|
||||
var rotatedHandPosition;
|
||||
var rotatedTipPosition;
|
||||
|
||||
function update(deltaTime) {
|
||||
if(Controller.getValue(Controller.Standard.RightPrimaryThumb)){
|
||||
pitchManager(deltaTime);
|
||||
}else if(!firstPress){
|
||||
firstPress = true;
|
||||
}
|
||||
if(firstPress && MyAvatar.headYaw){
|
||||
MyAvatar.headYaw -= MyAvatar.headYaw/10;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function pitchManager(deltaTime){
|
||||
|
||||
rotatedHandPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, -MyAvatar.bodyYaw, 0), MyAvatar.getRightHandPosition());
|
||||
rotatedTipPosition = Vec3.multiplyQbyV(Quat.fromPitchYawRollDegrees(0, -MyAvatar.bodyYaw, 0), MyAvatar.getRightHandTipPosition());
|
||||
|
||||
handCurrentVerticalRotation = Vec3.subtract(rotatedTipPosition, rotatedHandPosition).y;
|
||||
handCurrentHorizontalRotation = Vec3.subtract(rotatedTipPosition, rotatedHandPosition).x;
|
||||
|
||||
var handCurrentHorizontalRotationFiltered = handCurrentHorizontalRotation;
|
||||
|
||||
//to avoid yaw drift
|
||||
if((handCurrentHorizontalRotation - handPreviousHorizontalRotation) < EPSILON && (handCurrentHorizontalRotation - handPreviousHorizontalRotation) > -EPSILON){
|
||||
handCurrentHorizontalRotationFiltered = handPreviousHorizontalRotation;
|
||||
}
|
||||
|
||||
if(firstPress){
|
||||
handPreviousVerticalRotation = handCurrentVerticalRotation;
|
||||
handPreviousHorizontalRotation = handCurrentHorizontalRotation;
|
||||
firstPress = false;
|
||||
}
|
||||
|
||||
MyAvatar.headPitch += (handCurrentVerticalRotation - handPreviousVerticalRotation)*PITCH_MULTIPLIER*deltaTime;
|
||||
MyAvatar.headYaw -= (handCurrentHorizontalRotationFiltered - handPreviousHorizontalRotation)*YAW_MULTIPLIER*deltaTime;
|
||||
|
||||
|
||||
handPreviousVerticalRotation = handCurrentVerticalRotation;
|
||||
handPreviousHorizontalRotation = handCurrentHorizontalRotationFiltered;
|
||||
|
||||
|
||||
}
|
||||
|
||||
function clean(){
|
||||
MyAvatar.headYaw = 0.0;
|
||||
}
|
||||
|
||||
|
||||
Script.update.connect(update);
|
||||
Script.scriptEnding.connect(clean);
|
|
@ -25,6 +25,7 @@
|
|||
#include "RecurseOctreeToMapOperator.h"
|
||||
#include "LogHandler.h"
|
||||
|
||||
static const quint64 DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER = USECS_PER_MSEC * 50;
|
||||
|
||||
EntityTree::EntityTree(bool shouldReaverage) :
|
||||
Octree(shouldReaverage),
|
||||
|
@ -384,16 +385,15 @@ void EntityTree::deleteEntities(QSet<EntityItemID> entityIDs, bool force, bool i
|
|||
}
|
||||
|
||||
void EntityTree::processRemovedEntities(const DeleteEntityOperator& theOperator) {
|
||||
quint64 deletedAt = usecTimestampNow();
|
||||
const RemovedEntities& entities = theOperator.getEntities();
|
||||
foreach(const EntityToDeleteDetails& details, entities) {
|
||||
EntityItemPointer theEntity = details.entity;
|
||||
|
||||
if (getIsServer()) {
|
||||
// set up the deleted entities ID
|
||||
quint64 deletedAt = usecTimestampNow();
|
||||
_recentlyDeletedEntitiesLock.lockForWrite();
|
||||
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
|
||||
_recentlyDeletedEntityItemIDs.insert(deletedAt, theEntity->getEntityItemID());
|
||||
_recentlyDeletedEntitiesLock.unlock();
|
||||
}
|
||||
|
||||
if (_simulation) {
|
||||
|
@ -802,25 +802,37 @@ void EntityTree::update() {
|
|||
}
|
||||
|
||||
bool EntityTree::hasEntitiesDeletedSince(quint64 sinceTime) {
|
||||
quint64 considerEntitiesSince = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER;
|
||||
|
||||
// we can probably leverage the ordered nature of QMultiMap to do this quickly...
|
||||
bool hasSomethingNewer = false;
|
||||
|
||||
_recentlyDeletedEntitiesLock.lockForRead();
|
||||
QReadLocker locker(&_recentlyDeletedEntitiesLock);
|
||||
QMultiMap<quint64, QUuid>::const_iterator iterator = _recentlyDeletedEntityItemIDs.constBegin();
|
||||
while (iterator != _recentlyDeletedEntityItemIDs.constEnd()) {
|
||||
if (iterator.key() > sinceTime) {
|
||||
if (iterator.key() > considerEntitiesSince) {
|
||||
hasSomethingNewer = true;
|
||||
break; // if we have at least one item, we don't need to keep searching
|
||||
}
|
||||
++iterator;
|
||||
}
|
||||
_recentlyDeletedEntitiesLock.unlock();
|
||||
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
if (hasSomethingNewer) {
|
||||
int elapsed = usecTimestampNow() - considerEntitiesSince;
|
||||
int difference = considerEntitiesSince - sinceTime;
|
||||
qDebug() << "EntityTree::hasEntitiesDeletedSince() sinceTime:" << sinceTime
|
||||
<< "considerEntitiesSince:" << considerEntitiesSince << "elapsed:" << elapsed << "difference:" << difference;
|
||||
}
|
||||
#endif
|
||||
|
||||
return hasSomethingNewer;
|
||||
}
|
||||
|
||||
// sinceTime is an in/out parameter - it will be side effected with the last time sent out
|
||||
std::unique_ptr<NLPacket> EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_SEQUENCE sequenceNumber, quint64& sinceTime,
|
||||
bool& hasMore) {
|
||||
|
||||
quint64 considerEntitiesSince = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER;
|
||||
auto deletesPacket = NLPacket::create(PacketType::EntityErase);
|
||||
|
||||
// pack in flags
|
||||
|
@ -841,48 +853,56 @@ std::unique_ptr<NLPacket> EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S
|
|||
|
||||
// we keep a multi map of entity IDs to timestamps, we only want to include the entity IDs that have been
|
||||
// deleted since we last sent to this node
|
||||
_recentlyDeletedEntitiesLock.lockForRead();
|
||||
{
|
||||
QReadLocker locker(&_recentlyDeletedEntitiesLock);
|
||||
|
||||
bool hasFilledPacket = false;
|
||||
bool hasFilledPacket = false;
|
||||
|
||||
auto it = _recentlyDeletedEntityItemIDs.constBegin();
|
||||
while (it != _recentlyDeletedEntityItemIDs.constEnd()) {
|
||||
QList<QUuid> values = _recentlyDeletedEntityItemIDs.values(it.key());
|
||||
for (int valueItem = 0; valueItem < values.size(); ++valueItem) {
|
||||
auto it = _recentlyDeletedEntityItemIDs.constBegin();
|
||||
while (it != _recentlyDeletedEntityItemIDs.constEnd()) {
|
||||
QList<QUuid> values = _recentlyDeletedEntityItemIDs.values(it.key());
|
||||
for (int valueItem = 0; valueItem < values.size(); ++valueItem) {
|
||||
|
||||
// if the timestamp is more recent then out last sent time, include it
|
||||
if (it.key() > sinceTime) {
|
||||
QUuid entityID = values.at(valueItem);
|
||||
deletesPacket->write(entityID.toRfc4122());
|
||||
// if the timestamp is more recent then out last sent time, include it
|
||||
if (it.key() > considerEntitiesSince) {
|
||||
QUuid entityID = values.at(valueItem);
|
||||
|
||||
++numberOfIDs;
|
||||
// FIXME - we still seem to see cases where incorrect EntityIDs get sent from the server
|
||||
// to the client. These were causing "lost" entities like flashlights and laser pointers
|
||||
// now that we keep around some additional history of the erased entities and resend that
|
||||
// history for a longer time window, these entities are not "lost". But we haven't yet
|
||||
// found/fixed the underlying issue that caused bad UUIDs to be sent to some users.
|
||||
deletesPacket->write(entityID.toRfc4122());
|
||||
++numberOfIDs;
|
||||
|
||||
// check to make sure we have room for one more ID
|
||||
if (NUM_BYTES_RFC4122_UUID > deletesPacket->bytesAvailableForWrite()) {
|
||||
hasFilledPacket = true;
|
||||
break;
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << "EntityTree::encodeEntitiesDeletedSince() including:" << entityID;
|
||||
#endif
|
||||
|
||||
// check to make sure we have room for one more ID
|
||||
if (NUM_BYTES_RFC4122_UUID > deletesPacket->bytesAvailableForWrite()) {
|
||||
hasFilledPacket = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// check to see if we're about to return
|
||||
if (hasFilledPacket) {
|
||||
// let our caller know how far we got
|
||||
sinceTime = it.key();
|
||||
break;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// check to see if we're about to return
|
||||
if (hasFilledPacket) {
|
||||
// let our caller know how far we got
|
||||
sinceTime = it.key();
|
||||
|
||||
break;
|
||||
// if we got to the end, then we're done sending
|
||||
if (it == _recentlyDeletedEntityItemIDs.constEnd()) {
|
||||
hasMore = false;
|
||||
}
|
||||
|
||||
++it;
|
||||
}
|
||||
|
||||
// if we got to the end, then we're done sending
|
||||
if (it == _recentlyDeletedEntityItemIDs.constEnd()) {
|
||||
hasMore = false;
|
||||
}
|
||||
|
||||
_recentlyDeletedEntitiesLock.unlock();
|
||||
|
||||
// replace the count for the number of included IDs
|
||||
deletesPacket->seek(numberOfIDsPos);
|
||||
deletesPacket->writePrimitive(numberOfIDs);
|
||||
|
@ -893,14 +913,14 @@ std::unique_ptr<NLPacket> EntityTree::encodeEntitiesDeletedSince(OCTREE_PACKET_S
|
|||
|
||||
// called by the server when it knows all nodes have been sent deleted packets
|
||||
void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
|
||||
quint64 considerSinceTime = sinceTime - DELETED_ENTITIES_EXTRA_USECS_TO_CONSIDER;
|
||||
QSet<quint64> keysToRemove;
|
||||
|
||||
_recentlyDeletedEntitiesLock.lockForWrite();
|
||||
QWriteLocker locker(&_recentlyDeletedEntitiesLock);
|
||||
QMultiMap<quint64, QUuid>::iterator iterator = _recentlyDeletedEntityItemIDs.begin();
|
||||
|
||||
// First find all the keys in the map that are older and need to be deleted
|
||||
while (iterator != _recentlyDeletedEntityItemIDs.end()) {
|
||||
if (iterator.key() <= sinceTime) {
|
||||
if (iterator.key() <= considerSinceTime) {
|
||||
keysToRemove << iterator.key();
|
||||
}
|
||||
++iterator;
|
||||
|
@ -910,13 +930,14 @@ void EntityTree::forgetEntitiesDeletedBefore(quint64 sinceTime) {
|
|||
foreach (quint64 value, keysToRemove) {
|
||||
_recentlyDeletedEntityItemIDs.remove(value);
|
||||
}
|
||||
|
||||
_recentlyDeletedEntitiesLock.unlock();
|
||||
}
|
||||
|
||||
|
||||
// TODO: consider consolidating processEraseMessageDetails() and processEraseMessage()
|
||||
int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& sourceNode) {
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << "EntityTree::processEraseMessage()";
|
||||
#endif
|
||||
withWriteLock([&] {
|
||||
packet.seek(sizeof(OCTREE_PACKET_FLAGS) + sizeof(OCTREE_PACKET_SEQUENCE) + sizeof(OCTREE_PACKET_SENT_TIME));
|
||||
|
||||
|
@ -934,6 +955,9 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s
|
|||
}
|
||||
|
||||
QUuid entityID = QUuid::fromRfc4122(packet.readWithoutCopy(NUM_BYTES_RFC4122_UUID));
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << " ---- EntityTree::processEraseMessage() contained ID:" << entityID;
|
||||
#endif
|
||||
|
||||
EntityItemID entityItemID(entityID);
|
||||
entityItemIDsToDelete << entityItemID;
|
||||
|
@ -953,6 +977,9 @@ int EntityTree::processEraseMessage(NLPacket& packet, const SharedNodePointer& s
|
|||
// NOTE: Caller must lock the tree before calling this.
|
||||
// TODO: consider consolidating processEraseMessageDetails() and processEraseMessage()
|
||||
int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, const SharedNodePointer& sourceNode) {
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << "EntityTree::processEraseMessageDetails()";
|
||||
#endif
|
||||
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
|
||||
const unsigned char* dataAt = packetData;
|
||||
size_t packetLength = dataByteArray.size();
|
||||
|
@ -979,6 +1006,10 @@ int EntityTree::processEraseMessageDetails(const QByteArray& dataByteArray, cons
|
|||
dataAt += encodedID.size();
|
||||
processedBytes += encodedID.size();
|
||||
|
||||
#ifdef EXTRA_ERASE_DEBUGGING
|
||||
qDebug() << " ---- EntityTree::processEraseMessageDetails() contains id:" << entityID;
|
||||
#endif
|
||||
|
||||
EntityItemID entityItemID(entityID);
|
||||
entityItemIDsToDelete << entityItemID;
|
||||
|
||||
|
|
Loading…
Reference in a new issue