mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 11:08:06 +02:00
first cut at adding view frustum support to avatar mixer
This commit is contained in:
parent
92632e72b6
commit
a7750501c6
9 changed files with 123 additions and 1 deletions
|
@ -44,6 +44,7 @@ AvatarMixer::AvatarMixer(ReceivedMessage& message) :
|
|||
connect(DependencyManager::get<NodeList>().data(), &NodeList::nodeKilled, this, &AvatarMixer::nodeKilled);
|
||||
|
||||
auto& packetReceiver = DependencyManager::get<NodeList>()->getPacketReceiver();
|
||||
packetReceiver.registerListener(PacketType::ViewFrustum, this, "handleViewFrustumPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarData, this, "handleAvatarDataPacket");
|
||||
packetReceiver.registerListener(PacketType::AvatarIdentity, this, "handleAvatarIdentityPacket");
|
||||
packetReceiver.registerListener(PacketType::KillAvatar, this, "handleKillAvatarPacket");
|
||||
|
@ -275,6 +276,16 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
}
|
||||
// Not close enough to ignore
|
||||
nodeData->removeFromRadiusIgnoringSet(otherNode->getUUID());
|
||||
|
||||
|
||||
// Also check to see if the other node is in our view
|
||||
glm::vec3 otherNodeBoxScale = (otherData->getPosition() - otherData->getGlobalBoundingBoxCorner()) * 2.0f;
|
||||
AABox otherNodeBox(otherData->getGlobalBoundingBoxCorner(), otherNodeBoxScale);
|
||||
if (!nodeData->otherAvatarInView(otherNodeBox)) {
|
||||
qDebug() << "Avatar out of view!";
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
},
|
||||
|
@ -448,6 +459,18 @@ void AvatarMixer::nodeKilled(SharedNodePointer killedNode) {
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarMixer::handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->getOrCreateLinkedData(senderNode);
|
||||
|
||||
if (senderNode->getLinkedData()) {
|
||||
AvatarMixerClientData* nodeData = dynamic_cast<AvatarMixerClientData*>(senderNode->getLinkedData());
|
||||
if (nodeData != nullptr) {
|
||||
nodeData->readViewFrustumPacket(message->getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AvatarMixer::handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode) {
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
nodeList->updateNodeWithDataFromPacket(message, senderNode);
|
||||
|
|
|
@ -34,6 +34,7 @@ public slots:
|
|||
void sendStatsPacket() override;
|
||||
|
||||
private slots:
|
||||
void handleViewFrustumPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleAvatarDataPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleAvatarIdentityPacket(QSharedPointer<ReceivedMessage> message, SharedNodePointer senderNode);
|
||||
void handleKillAvatarPacket(QSharedPointer<ReceivedMessage> message);
|
||||
|
|
|
@ -57,6 +57,13 @@ void AvatarMixerClientData::ignoreOther(SharedNodePointer self, SharedNodePointe
|
|||
}
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::readViewFrustumPacket(const QByteArray& message) {
|
||||
_currentViewFrustumIsValid = true;
|
||||
_currentViewFrustum.fromByteArray(message);
|
||||
qDebug() << __FUNCTION__;
|
||||
_currentViewFrustum.printDebugDetails();
|
||||
}
|
||||
|
||||
void AvatarMixerClientData::loadJSONStats(QJsonObject& jsonObject) const {
|
||||
jsonObject["display_name"] = _avatar->getDisplayName();
|
||||
jsonObject["full_rate_distance"] = _fullRateDistance;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include <PortableHighResolutionClock.h>
|
||||
#include <SimpleMovingAverage.h>
|
||||
#include <UUIDHasher.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
const QString OUTBOUND_AVATAR_DATA_STATS_KEY = "outbound_av_data_kbps";
|
||||
const QString INBOUND_AVATAR_DATA_STATS_KEY = "inbound_av_data_kbps";
|
||||
|
@ -87,6 +88,12 @@ public:
|
|||
void removeFromRadiusIgnoringSet(const QUuid& other) { _radiusIgnoredOthers.erase(other); }
|
||||
void ignoreOther(SharedNodePointer self, SharedNodePointer other);
|
||||
|
||||
void readViewFrustumPacket(const QByteArray& message);
|
||||
|
||||
bool otherAvatarInView(const AABox& otherAvatarBox) {
|
||||
return !_currentViewFrustumIsValid || _currentViewFrustum.boxIntersectsKeyhole(otherAvatarBox);
|
||||
}
|
||||
|
||||
private:
|
||||
AvatarSharedPointer _avatar { new AvatarData() };
|
||||
|
||||
|
@ -108,6 +115,8 @@ private:
|
|||
|
||||
SimpleMovingAverage _avgOtherAvatarDataRate;
|
||||
std::unordered_set<QUuid> _radiusIgnoredOthers;
|
||||
ViewFrustum _currentViewFrustum;
|
||||
bool _currentViewFrustumIsValid { false };
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarMixerClientData_h
|
||||
|
|
|
@ -4176,6 +4176,7 @@ void Application::update(float deltaTime) {
|
|||
if (DependencyManager::get<SceneScriptingInterface>()->shouldRenderEntities()) {
|
||||
queryOctree(NodeType::EntityServer, PacketType::EntityQuery, _entityServerJurisdictions);
|
||||
}
|
||||
sendAvatarViewFrustum();
|
||||
_lastQueriedViewFrustum = _viewFrustum;
|
||||
}
|
||||
}
|
||||
|
@ -4215,6 +4216,14 @@ void Application::update(float deltaTime) {
|
|||
AnimDebugDraw::getInstance().update();
|
||||
}
|
||||
|
||||
void Application::sendAvatarViewFrustum() {
|
||||
QByteArray viewFrustumByteArray = _viewFrustum.toByteArray();
|
||||
auto avatarPacket = NLPacket::create(PacketType::ViewFrustum, viewFrustumByteArray.size());
|
||||
avatarPacket->write(viewFrustumByteArray);
|
||||
|
||||
DependencyManager::get<NodeList>()->broadcastToNodes(std::move(avatarPacket), NodeSet() << NodeType::AvatarMixer);
|
||||
}
|
||||
|
||||
|
||||
int Application::sendNackPackets() {
|
||||
|
||||
|
|
|
@ -415,6 +415,7 @@ private:
|
|||
void renderRearViewMirror(RenderArgs* renderArgs, const QRect& region, bool isZoomed);
|
||||
|
||||
int sendNackPackets();
|
||||
void sendAvatarViewFrustum();
|
||||
|
||||
std::shared_ptr<MyAvatar> getMyAvatar() const;
|
||||
|
||||
|
|
|
@ -101,7 +101,8 @@ public:
|
|||
NodeKickRequest,
|
||||
NodeMuteRequest,
|
||||
RadiusIgnoreRequest,
|
||||
LAST_PACKET_TYPE = RadiusIgnoreRequest
|
||||
ViewFrustum,
|
||||
LAST_PACKET_TYPE = ViewFrustum
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -130,6 +130,73 @@ const char* ViewFrustum::debugPlaneName (int plane) const {
|
|||
return "Unknown";
|
||||
}
|
||||
|
||||
void ViewFrustum::fromByteArray(const QByteArray& input) {
|
||||
|
||||
// From the wire!
|
||||
glm::vec3 cameraPosition;
|
||||
glm::quat cameraOrientation;
|
||||
float cameraCenterRadius;
|
||||
float cameraFov;
|
||||
float cameraAspectRatio;
|
||||
float cameraNearClip;
|
||||
float cameraFarClip;
|
||||
|
||||
const unsigned char* startPosition = reinterpret_cast<const unsigned char*>(input.constData());
|
||||
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(&cameraCenterRadius, sourceBuffer, sizeof(cameraCenterRadius));
|
||||
sourceBuffer += sizeof(cameraCenterRadius);
|
||||
|
||||
setPosition(cameraPosition);
|
||||
setOrientation(cameraOrientation);
|
||||
setCenterRadius(cameraCenterRadius);
|
||||
|
||||
// Also make sure it's got the correct lens details from the camera
|
||||
const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f;
|
||||
float originalFOV = cameraFov;
|
||||
float wideFOV = originalFOV + VIEW_FRUSTUM_FOV_OVERSEND;
|
||||
|
||||
if (0.0f != cameraAspectRatio &&
|
||||
0.0f != cameraNearClip &&
|
||||
0.0f != cameraFarClip &&
|
||||
cameraNearClip != cameraFarClip) {
|
||||
setProjection(glm::perspective(
|
||||
glm::radians(wideFOV), // hack
|
||||
cameraAspectRatio,
|
||||
cameraNearClip,
|
||||
cameraFarClip));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
QByteArray ViewFrustum::toByteArray() {
|
||||
static const int LARGE_ENOUGH = 1024;
|
||||
QByteArray viewFrustumDataByteArray(LARGE_ENOUGH, 0);
|
||||
unsigned char* destinationBuffer = reinterpret_cast<unsigned char*>(viewFrustumDataByteArray.data());
|
||||
unsigned char* startPosition = destinationBuffer;
|
||||
|
||||
// camera details
|
||||
memcpy(destinationBuffer, &_position, sizeof(_position));
|
||||
destinationBuffer += sizeof(_position);
|
||||
destinationBuffer += packOrientationQuatToBytes(destinationBuffer, _orientation);
|
||||
destinationBuffer += packFloatAngleToTwoByte(destinationBuffer, _fieldOfView);
|
||||
destinationBuffer += packFloatRatioToTwoByte(destinationBuffer, _aspectRatio);
|
||||
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _nearClip);
|
||||
destinationBuffer += packClipValueToTwoByte(destinationBuffer, _farClip);
|
||||
memcpy(destinationBuffer, &_centerSphereRadius, sizeof(_centerSphereRadius));
|
||||
destinationBuffer += sizeof(_centerSphereRadius);
|
||||
|
||||
return viewFrustumDataByteArray.left(destinationBuffer - startPosition);
|
||||
}
|
||||
|
||||
ViewFrustum::intersection ViewFrustum::calculateCubeFrustumIntersection(const AACube& cube) const {
|
||||
// only check against frustum
|
||||
ViewFrustum::intersection result = INSIDE;
|
||||
|
|
|
@ -139,6 +139,10 @@ public:
|
|||
const ::Plane* getPlanes() const { return _planes; }
|
||||
|
||||
void invalidate(); // causes all reasonable intersection tests to fail
|
||||
|
||||
QByteArray toByteArray();
|
||||
void fromByteArray(const QByteArray& input);
|
||||
|
||||
private:
|
||||
glm::mat4 _view;
|
||||
glm::mat4 _projection;
|
||||
|
|
Loading…
Reference in a new issue