mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-05-29 09:39:55 +02:00
first cut at particle renderer cleanup particle jurisdiction listener fix storage of particles
This commit is contained in:
parent
4df2f2189d
commit
2ca628fdf1
17 changed files with 333 additions and 9 deletions
|
@ -65,7 +65,10 @@ void Agent::run() {
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
nodeList->setOwnerType(NODE_TYPE_AGENT);
|
nodeList->setOwnerType(NODE_TYPE_AGENT);
|
||||||
|
|
||||||
const char AGENT_NODE_TYPES_OF_INTEREST[1] = { NODE_TYPE_VOXEL_SERVER };
|
// XXXBHG - this seems less than ideal. There might be classes (like jurisdiction listeners, that need access to
|
||||||
|
// other node types, but for them to get access to those node types, we have to add them here. It seems like
|
||||||
|
// NodeList should support adding types of interest
|
||||||
|
const NODE_TYPE AGENT_NODE_TYPES_OF_INTEREST[] = { NODE_TYPE_VOXEL_SERVER, NODE_TYPE_PARTICLE_SERVER };
|
||||||
|
|
||||||
nodeList->setNodeTypesOfInterest(AGENT_NODE_TYPES_OF_INTEREST, sizeof(AGENT_NODE_TYPES_OF_INTEREST));
|
nodeList->setNodeTypesOfInterest(AGENT_NODE_TYPES_OF_INTEREST, sizeof(AGENT_NODE_TYPES_OF_INTEREST));
|
||||||
|
|
||||||
|
|
|
@ -51,6 +51,9 @@ DomainServer::DomainServer(int argc, char* argv[]) :
|
||||||
|
|
||||||
const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig";
|
const char VOXEL_CONFIG_OPTION[] = "--voxelServerConfig";
|
||||||
_voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION);
|
_voxelServerConfig = getCmdOption(argc, (const char**) argv, VOXEL_CONFIG_OPTION);
|
||||||
|
|
||||||
|
const char PARTICLE_CONFIG_OPTION[] = "--particleServerConfig";
|
||||||
|
_particleServerConfig = getCmdOption(argc, (const char**) argv, PARTICLE_CONFIG_OPTION);
|
||||||
|
|
||||||
// setup the mongoose web server
|
// setup the mongoose web server
|
||||||
struct mg_callbacks callbacks = {};
|
struct mg_callbacks callbacks = {};
|
||||||
|
|
|
@ -84,6 +84,7 @@ include(${MACRO_DIR}/LinkHifiLibrary.cmake)
|
||||||
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(shared ${TARGET_NAME} ${ROOT_DIR})
|
||||||
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(octree ${TARGET_NAME} ${ROOT_DIR})
|
||||||
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(voxels ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
link_hifi_library(particles ${TARGET_NAME} ${ROOT_DIR})
|
||||||
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(avatars ${TARGET_NAME} ${ROOT_DIR})
|
||||||
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
link_hifi_library(audio ${TARGET_NAME} ${ROOT_DIR})
|
||||||
|
|
||||||
|
|
|
@ -3004,6 +3004,9 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
|
||||||
_voxels.render(Menu::getInstance()->isOptionChecked(MenuOption::VoxelTextures));
|
_voxels.render(Menu::getInstance()->isOptionChecked(MenuOption::VoxelTextures));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// render particles...
|
||||||
|
_particles.render();
|
||||||
|
|
||||||
// restore default, white specular
|
// restore default, white specular
|
||||||
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR);
|
glMaterialfv(GL_FRONT, GL_SPECULAR, WHITE_SPECULAR_COLOR);
|
||||||
|
@ -4217,6 +4220,12 @@ void* Application::networkReceive(void* args) {
|
||||||
QMetaObject::invokeMethod(&app->_audio, "addReceivedAudioToBuffer", Qt::QueuedConnection,
|
QMetaObject::invokeMethod(&app->_audio, "addReceivedAudioToBuffer", Qt::QueuedConnection,
|
||||||
Q_ARG(QByteArray, QByteArray((char*) app->_incomingPacket, bytesReceived)));
|
Q_ARG(QByteArray, QByteArray((char*) app->_incomingPacket, bytesReceived)));
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case PACKET_TYPE_PARTICLE_DATA: {
|
||||||
|
app->_particles.processDatagram(QByteArray((char*) app->_incomingPacket, bytesReceived),
|
||||||
|
senderSockAddr);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case PACKET_TYPE_VOXEL_DATA:
|
case PACKET_TYPE_VOXEL_DATA:
|
||||||
case PACKET_TYPE_VOXEL_ERASE:
|
case PACKET_TYPE_VOXEL_ERASE:
|
||||||
case PACKET_TYPE_OCTREE_STATS:
|
case PACKET_TYPE_OCTREE_STATS:
|
||||||
|
|
|
@ -63,6 +63,7 @@
|
||||||
#include "ui/VoxelStatsDialog.h"
|
#include "ui/VoxelStatsDialog.h"
|
||||||
#include "ui/RearMirrorTools.h"
|
#include "ui/RearMirrorTools.h"
|
||||||
#include "ui/LodToolsDialog.h"
|
#include "ui/LodToolsDialog.h"
|
||||||
|
#include "ParticleTreeRenderer.h"
|
||||||
|
|
||||||
class QAction;
|
class QAction;
|
||||||
class QActionGroup;
|
class QActionGroup;
|
||||||
|
@ -341,6 +342,8 @@ private:
|
||||||
VoxelImporter _voxelImporter;
|
VoxelImporter _voxelImporter;
|
||||||
VoxelSystem _sharedVoxelSystem;
|
VoxelSystem _sharedVoxelSystem;
|
||||||
ViewFrustum _sharedVoxelSystemViewFrustum;
|
ViewFrustum _sharedVoxelSystemViewFrustum;
|
||||||
|
|
||||||
|
ParticleTreeRenderer _particles;
|
||||||
|
|
||||||
QByteArray _voxelsFilename;
|
QByteArray _voxelsFilename;
|
||||||
bool _wantToKillLocalVoxels;
|
bool _wantToKillLocalVoxels;
|
||||||
|
|
37
interface/src/ParticleTreeRenderer.cpp
Normal file
37
interface/src/ParticleTreeRenderer.cpp
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
//
|
||||||
|
// ParticleTreeRenderer.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/6/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include "InterfaceConfig.h"
|
||||||
|
|
||||||
|
#include "ParticleTreeRenderer.h"
|
||||||
|
|
||||||
|
ParticleTreeRenderer::ParticleTreeRenderer() :
|
||||||
|
OctreeRenderer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
ParticleTreeRenderer::~ParticleTreeRenderer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void ParticleTreeRenderer::renderElement(OctreeElement* element) {
|
||||||
|
// actually render it here...
|
||||||
|
// we need to iterate the actual particles of the element
|
||||||
|
ParticleTreeElement* particleTreeElement = (ParticleTreeElement*)element;
|
||||||
|
|
||||||
|
const std::vector<Particle>& particles = particleTreeElement->getParticles();
|
||||||
|
|
||||||
|
uint16_t numberOfParticles = particles.size();
|
||||||
|
|
||||||
|
glBegin(GL_POINTS);
|
||||||
|
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||||
|
const Particle& particle = particles[i];
|
||||||
|
// render particle aspoints
|
||||||
|
glVertex3f(particle.getPosition().x, particle.getPosition().y, particle.getPosition().z);
|
||||||
|
}
|
||||||
|
glEnd();
|
||||||
|
}
|
39
interface/src/ParticleTreeRenderer.h
Normal file
39
interface/src/ParticleTreeRenderer.h
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
//
|
||||||
|
// ParticleTreeRenderer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/6/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__ParticleTreeRenderer__
|
||||||
|
#define __hifi__ParticleTreeRenderer__
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <Octree.h>
|
||||||
|
#include <OctreePacketData.h>
|
||||||
|
#include <OctreeRenderer.h>
|
||||||
|
#include <ParticleTree.h>
|
||||||
|
#include <ViewFrustum.h>
|
||||||
|
|
||||||
|
// Generic client side Octree renderer class.
|
||||||
|
class ParticleTreeRenderer : public OctreeRenderer {
|
||||||
|
public:
|
||||||
|
ParticleTreeRenderer();
|
||||||
|
virtual ~ParticleTreeRenderer();
|
||||||
|
|
||||||
|
virtual Octree* createTree() { return new ParticleTree(true); }
|
||||||
|
virtual NODE_TYPE getMyNodeType() const { return NODE_TYPE_PARTICLE_SERVER; }
|
||||||
|
virtual PACKET_TYPE getMyQueryMessageType() const { return PACKET_TYPE_PARTICLE_QUERY; }
|
||||||
|
virtual PACKET_TYPE getExpectedPacketType() const { return PACKET_TYPE_PARTICLE_DATA; }
|
||||||
|
virtual void renderElement(OctreeElement* element);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__ParticleTreeRenderer__) */
|
|
@ -42,7 +42,7 @@ void OctreeInboundPacketProcessor::resetStats() {
|
||||||
void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr,
|
void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockAddr,
|
||||||
unsigned char* packetData, ssize_t packetLength) {
|
unsigned char* packetData, ssize_t packetLength) {
|
||||||
|
|
||||||
bool debugProcessPacket = _myServer->wantsVerboseDebug();
|
bool debugProcessPacket = true; //_myServer->wantsVerboseDebug();
|
||||||
|
|
||||||
if (debugProcessPacket) {
|
if (debugProcessPacket) {
|
||||||
printf("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%ld\n", packetData, packetLength);
|
printf("OctreeInboundPacketProcessor::processPacket() packetData=%p packetLength=%ld\n", packetData, packetLength);
|
||||||
|
@ -66,8 +66,9 @@ void OctreeInboundPacketProcessor::processPacket(const HifiSockAddr& senderSockA
|
||||||
uint64_t lockWaitTime = 0;
|
uint64_t lockWaitTime = 0;
|
||||||
|
|
||||||
if (_myServer->wantsDebugReceiving()) {
|
if (_myServer->wantsDebugReceiving()) {
|
||||||
printf("PROCESSING THREAD: got %c - %d command from client receivedBytes=%ld sequence=%d transitTime=%llu usecs\n",
|
printf("PROCESSING THREAD: got '%c' packet - %d command from client "
|
||||||
packetType, _receivedPacketCount, packetLength, sequence, transitTime);
|
"receivedBytes=%ld sequence=%d transitTime=%llu usecs\n",
|
||||||
|
packetType, _receivedPacketCount, packetLength, sequence, transitTime);
|
||||||
}
|
}
|
||||||
int atByte = numBytesPacketHeader + sizeof(sequence) + sizeof(sentAt);
|
int atByte = numBytesPacketHeader + sizeof(sequence) + sizeof(sentAt);
|
||||||
unsigned char* editData = (unsigned char*)&packetData[atByte];
|
unsigned char* editData = (unsigned char*)&packetData[atByte];
|
||||||
|
|
|
@ -16,12 +16,16 @@
|
||||||
#include "JurisdictionListener.h"
|
#include "JurisdictionListener.h"
|
||||||
|
|
||||||
|
|
||||||
JurisdictionListener::JurisdictionListener(PacketSenderNotify* notify) :
|
JurisdictionListener::JurisdictionListener(NODE_TYPE type, PacketSenderNotify* notify) :
|
||||||
PacketSender(notify, JurisdictionListener::DEFAULT_PACKETS_PER_SECOND)
|
PacketSender(notify, JurisdictionListener::DEFAULT_PACKETS_PER_SECOND)
|
||||||
{
|
{
|
||||||
|
_nodeType = type;
|
||||||
ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to
|
ReceivedPacketProcessor::_dontSleep = true; // we handle sleeping so this class doesn't need to
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
nodeList->addHook(this);
|
nodeList->addHook(this);
|
||||||
|
|
||||||
|
qDebug("JurisdictionListener::JurisdictionListener(NODE_TYPE type=%c)\n", type);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JurisdictionListener::~JurisdictionListener() {
|
JurisdictionListener::~JurisdictionListener() {
|
||||||
|
@ -40,6 +44,8 @@ void JurisdictionListener::nodeKilled(Node* node) {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool JurisdictionListener::queueJurisdictionRequest() {
|
bool JurisdictionListener::queueJurisdictionRequest() {
|
||||||
|
qDebug() << "JurisdictionListener::queueJurisdictionRequest()\n";
|
||||||
|
|
||||||
static unsigned char buffer[MAX_PACKET_SIZE];
|
static unsigned char buffer[MAX_PACKET_SIZE];
|
||||||
unsigned char* bufferOut = &buffer[0];
|
unsigned char* bufferOut = &buffer[0];
|
||||||
ssize_t sizeOut = populateTypeAndVersion(bufferOut, PACKET_TYPE_JURISDICTION_REQUEST);
|
ssize_t sizeOut = populateTypeAndVersion(bufferOut, PACKET_TYPE_JURISDICTION_REQUEST);
|
||||||
|
@ -47,7 +53,11 @@ bool JurisdictionListener::queueJurisdictionRequest() {
|
||||||
|
|
||||||
NodeList* nodeList = NodeList::getInstance();
|
NodeList* nodeList = NodeList::getInstance();
|
||||||
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
for (NodeList::iterator node = nodeList->begin(); node != nodeList->end(); node++) {
|
||||||
if (nodeList->getNodeActiveSocketOrPing(&(*node)) && node->getType() == NODE_TYPE_VOXEL_SERVER) {
|
|
||||||
|
qDebug() << "Hello..." << *node << "\n";
|
||||||
|
|
||||||
|
if (nodeList->getNodeActiveSocketOrPing(&(*node)) &&
|
||||||
|
node->getType() == getNodeType()) {
|
||||||
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
const HifiSockAddr* nodeAddress = node->getActiveSocket();
|
||||||
PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
|
PacketSender::queuePacketForSending(*nodeAddress, bufferOut, sizeOut);
|
||||||
nodeCount++;
|
nodeCount++;
|
||||||
|
|
|
@ -26,7 +26,7 @@ public:
|
||||||
static const int DEFAULT_PACKETS_PER_SECOND = 1;
|
static const int DEFAULT_PACKETS_PER_SECOND = 1;
|
||||||
static const int NO_SERVER_CHECK_RATE = 60; // if no servers yet detected, keep checking at 60fps
|
static const int NO_SERVER_CHECK_RATE = 60; // if no servers yet detected, keep checking at 60fps
|
||||||
|
|
||||||
JurisdictionListener(PacketSenderNotify* notify = NULL);
|
JurisdictionListener(NODE_TYPE type = NODE_TYPE_VOXEL_SERVER, PacketSenderNotify* notify = NULL);
|
||||||
~JurisdictionListener();
|
~JurisdictionListener();
|
||||||
|
|
||||||
virtual bool process();
|
virtual bool process();
|
||||||
|
@ -38,6 +38,9 @@ public:
|
||||||
/// Called by NodeList to inform us that a node has been killed.
|
/// Called by NodeList to inform us that a node has been killed.
|
||||||
void nodeKilled(Node* node);
|
void nodeKilled(Node* node);
|
||||||
|
|
||||||
|
NODE_TYPE getNodeType() const { return _nodeType; }
|
||||||
|
void setNodeType(NODE_TYPE type) { _nodeType = type; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/// Callback for processing of received packets. Will process any queued PACKET_TYPE_JURISDICTION and update the
|
/// Callback for processing of received packets. Will process any queued PACKET_TYPE_JURISDICTION and update the
|
||||||
/// jurisdiction map member variable
|
/// jurisdiction map member variable
|
||||||
|
@ -49,6 +52,7 @@ protected:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
NodeToJurisdictionMap _jurisdictions;
|
NodeToJurisdictionMap _jurisdictions;
|
||||||
|
NODE_TYPE _nodeType;
|
||||||
|
|
||||||
bool queueJurisdictionRequest();
|
bool queueJurisdictionRequest();
|
||||||
};
|
};
|
||||||
|
|
129
libraries/octree/src/OctreeRenderer.cpp
Normal file
129
libraries/octree/src/OctreeRenderer.cpp
Normal file
|
@ -0,0 +1,129 @@
|
||||||
|
//
|
||||||
|
// OctreeRenderer.cpp
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/6/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include <PerfStat.h>
|
||||||
|
#include "OctreeRenderer.h"
|
||||||
|
|
||||||
|
OctreeRenderer::OctreeRenderer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
OctreeRenderer::~OctreeRenderer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeRenderer::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr) {
|
||||||
|
|
||||||
|
bool showTimingDetails = false; // Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
|
||||||
|
bool extraDebugging = false; // Menu::getInstance()->isOptionChecked(MenuOption::ExtraDebugging)
|
||||||
|
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram()",showTimingDetails);
|
||||||
|
|
||||||
|
const unsigned char* packetData = (const unsigned char*)dataByteArray.constData();
|
||||||
|
int packetLength = dataByteArray.size();
|
||||||
|
|
||||||
|
unsigned char command = *packetData;
|
||||||
|
int numBytesPacketHeader = numBytesForPacketHeader(packetData);
|
||||||
|
|
||||||
|
PACKET_TYPE expectedType = getExpectedPacketType();
|
||||||
|
|
||||||
|
if(command == expectedType) {
|
||||||
|
PerformanceWarning warn(showTimingDetails, "OctreeRenderer::processDatagram expected PACKET_TYPE",showTimingDetails);
|
||||||
|
|
||||||
|
const unsigned char* dataAt = packetData + numBytesPacketHeader;
|
||||||
|
|
||||||
|
OCTREE_PACKET_FLAGS flags = (*(OCTREE_PACKET_FLAGS*)(dataAt));
|
||||||
|
dataAt += sizeof(OCTREE_PACKET_FLAGS);
|
||||||
|
OCTREE_PACKET_SEQUENCE sequence = (*(OCTREE_PACKET_SEQUENCE*)dataAt);
|
||||||
|
dataAt += sizeof(OCTREE_PACKET_SEQUENCE);
|
||||||
|
|
||||||
|
OCTREE_PACKET_SENT_TIME sentAt = (*(OCTREE_PACKET_SENT_TIME*)dataAt);
|
||||||
|
dataAt += sizeof(OCTREE_PACKET_SENT_TIME);
|
||||||
|
|
||||||
|
bool packetIsColored = oneAtBit(flags, PACKET_IS_COLOR_BIT);
|
||||||
|
bool packetIsCompressed = oneAtBit(flags, PACKET_IS_COMPRESSED_BIT);
|
||||||
|
|
||||||
|
OCTREE_PACKET_SENT_TIME arrivedAt = usecTimestampNow();
|
||||||
|
int flightTime = arrivedAt - sentAt;
|
||||||
|
|
||||||
|
OCTREE_PACKET_INTERNAL_SECTION_SIZE sectionLength = 0;
|
||||||
|
int dataBytes = packetLength - OCTREE_PACKET_HEADER_SIZE;
|
||||||
|
|
||||||
|
int subsection = 1;
|
||||||
|
while (dataBytes > 0) {
|
||||||
|
if (packetIsCompressed) {
|
||||||
|
if (dataBytes > sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE)) {
|
||||||
|
sectionLength = (*(OCTREE_PACKET_INTERNAL_SECTION_SIZE*)dataAt);
|
||||||
|
dataAt += sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
||||||
|
dataBytes -= sizeof(OCTREE_PACKET_INTERNAL_SECTION_SIZE);
|
||||||
|
} else {
|
||||||
|
sectionLength = 0;
|
||||||
|
dataBytes = 0; // stop looping something is wrong
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
sectionLength = dataBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (sectionLength) {
|
||||||
|
// ask the VoxelTree to read the bitstream into the tree
|
||||||
|
ReadBitstreamToTreeParams args(packetIsColored ? WANT_COLOR : NO_COLOR, WANT_EXISTS_BITS, NULL,
|
||||||
|
getDataSourceUUID());
|
||||||
|
_tree->lockForWrite();
|
||||||
|
OctreePacketData packetData(packetIsCompressed);
|
||||||
|
packetData.loadFinalizedContent(dataAt, sectionLength);
|
||||||
|
if (extraDebugging) {
|
||||||
|
qDebug("OctreeRenderer::processDatagram() ... Got Packet Section"
|
||||||
|
" color:%s compressed:%s sequence: %u flight:%d usec size:%d data:%d"
|
||||||
|
" subsection:%d sectionLength:%d uncompressed:%d\n",
|
||||||
|
debug::valueOf(packetIsColored), debug::valueOf(packetIsCompressed),
|
||||||
|
sequence, flightTime, packetLength, dataBytes, subsection, sectionLength, packetData.getUncompressedSize());
|
||||||
|
}
|
||||||
|
_tree->readBitstreamToTree(packetData.getUncompressedData(), packetData.getUncompressedSize(), args);
|
||||||
|
_tree->unlock();
|
||||||
|
|
||||||
|
dataBytes -= sectionLength;
|
||||||
|
dataAt += sectionLength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
subsection++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// setup rendering for the new items...
|
||||||
|
//setupNewVoxelsForDrawingSingleNode(DONT_BAIL_EARLY);
|
||||||
|
|
||||||
|
// handle bandwidth meter stuff??? seems like this would be better done in application...
|
||||||
|
//Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::VOXELS).updateValue(numBytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeRenderer::init() {
|
||||||
|
}
|
||||||
|
|
||||||
|
class RenderArgs {
|
||||||
|
public:
|
||||||
|
OctreeRenderer* _renderer;
|
||||||
|
ViewFrustum* _viewFrustum;
|
||||||
|
};
|
||||||
|
|
||||||
|
bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) {
|
||||||
|
RenderArgs* args = static_cast<RenderArgs*>(extraData);
|
||||||
|
if (element->isInView(*args->_viewFrustum)) {
|
||||||
|
if (element->hasContent()) {
|
||||||
|
args->_renderer->renderElement(element);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
// if not in view stop recursing
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void OctreeRenderer::render() {
|
||||||
|
RenderArgs args = { this, _viewFrustum };
|
||||||
|
_tree->recurseTreeWithOperation(renderOperation, &args);
|
||||||
|
}
|
57
libraries/octree/src/OctreeRenderer.h
Normal file
57
libraries/octree/src/OctreeRenderer.h
Normal file
|
@ -0,0 +1,57 @@
|
||||||
|
//
|
||||||
|
// OctreeRenderer.h
|
||||||
|
// hifi
|
||||||
|
//
|
||||||
|
// Created by Brad Hefta-Gaub on 12/6/13.
|
||||||
|
// Copyright (c) 2013 High Fidelity, Inc. All rights reserved.
|
||||||
|
//
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef __hifi__OctreeRenderer__
|
||||||
|
#define __hifi__OctreeRenderer__
|
||||||
|
|
||||||
|
#include <glm/glm.hpp>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <NodeTypes.h>
|
||||||
|
#include <PacketHeaders.h>
|
||||||
|
#include <SharedUtil.h>
|
||||||
|
#include "Octree.h"
|
||||||
|
#include "OctreePacketData.h"
|
||||||
|
#include "ViewFrustum.h"
|
||||||
|
|
||||||
|
// Generic client side Octree renderer class.
|
||||||
|
class OctreeRenderer {
|
||||||
|
public:
|
||||||
|
OctreeRenderer();
|
||||||
|
virtual ~OctreeRenderer();
|
||||||
|
|
||||||
|
virtual Octree* createTree() = 0;
|
||||||
|
virtual NODE_TYPE getMyNodeType() const = 0;
|
||||||
|
virtual PACKET_TYPE getMyQueryMessageType() const = 0;
|
||||||
|
virtual PACKET_TYPE getExpectedPacketType() const = 0;
|
||||||
|
virtual void renderElement(OctreeElement* element) = 0;
|
||||||
|
|
||||||
|
/// process incoming data
|
||||||
|
void processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& senderSockAddr);
|
||||||
|
|
||||||
|
/// initialize and GPU/rendering related resources
|
||||||
|
void init();
|
||||||
|
|
||||||
|
/// render the content of the octree
|
||||||
|
virtual void render();
|
||||||
|
|
||||||
|
void setDataSourceUUID(const QUuid& dataSourceUUID) { _dataSourceUUID = dataSourceUUID; }
|
||||||
|
const QUuid& getDataSourceUUID() const { return _dataSourceUUID; }
|
||||||
|
ViewFrustum* getViewFrustum() const { return _viewFrustum; }
|
||||||
|
void setViewFrustum(ViewFrustum* viewFrustum) { _viewFrustum = viewFrustum; }
|
||||||
|
|
||||||
|
static bool renderOperation(OctreeElement* element, void* extraData);
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Octree* _tree;
|
||||||
|
QUuid _dataSourceUUID;
|
||||||
|
ViewFrustum* _viewFrustum;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* defined(__hifi__OctreeRenderer__) */
|
|
@ -8,7 +8,9 @@
|
||||||
|
|
||||||
#include "ParticleScriptingInterface.h"
|
#include "ParticleScriptingInterface.h"
|
||||||
|
|
||||||
ParticleScriptingInterface::ParticleScriptingInterface() {
|
ParticleScriptingInterface::ParticleScriptingInterface() :
|
||||||
|
_jurisdictionListener(NODE_TYPE_PARTICLE_SERVER)
|
||||||
|
{
|
||||||
_jurisdictionListener.initialize(true);
|
_jurisdictionListener.initialize(true);
|
||||||
_particlePacketSender.setServerJurisdictions(_jurisdictionListener.getJurisdictions());
|
_particlePacketSender.setServerJurisdictions(_jurisdictionListener.getJurisdictions());
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,15 @@ void ParticleTree::storeParticle(const Particle& particle) {
|
||||||
glm::vec3 position = particle.getPosition();
|
glm::vec3 position = particle.getPosition();
|
||||||
float size = particle.getRadius();
|
float size = particle.getRadius();
|
||||||
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
ParticleTreeElement* element = (ParticleTreeElement*)getOrCreateChildElementAt(position.x, position.y, position.z, size);
|
||||||
|
|
||||||
|
printf("ParticleTree::storeParticle() element=%p particle.getPosition()=%f,%f,%f\n",
|
||||||
|
element,
|
||||||
|
particle.getPosition().x, particle.getPosition().y, particle.getPosition().z);
|
||||||
|
|
||||||
element->storeParticle(particle);
|
element->storeParticle(particle);
|
||||||
|
|
||||||
|
// what else do we need to do here to get reaveraging to work
|
||||||
|
_isDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength,
|
||||||
|
@ -41,7 +49,12 @@ int ParticleTree::processEditPacketData(PACKET_TYPE packetType, unsigned char* p
|
||||||
// we handle these types of "edit" packets
|
// we handle these types of "edit" packets
|
||||||
switch (packetType) {
|
switch (packetType) {
|
||||||
case PACKET_TYPE_PARTICLE_ADD: {
|
case PACKET_TYPE_PARTICLE_ADD: {
|
||||||
|
|
||||||
|
printf("got PACKET_TYPE_PARTICLE_ADD....\n");
|
||||||
Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes);
|
Particle newParticle = Particle::fromEditPacket(editData, maxLength, processedBytes);
|
||||||
|
|
||||||
|
printf("newParticle...getPosition()=%f,%f,%f\n", newParticle.getPosition().x, newParticle.getPosition().y, newParticle.getPosition().z);
|
||||||
|
|
||||||
storeParticle(newParticle);
|
storeParticle(newParticle);
|
||||||
|
|
||||||
// It seems like we need some way to send the ID back to the creator??
|
// It seems like we need some way to send the ID back to the creator??
|
||||||
|
|
|
@ -78,7 +78,9 @@ int ParticleTreeElement::readElementDataFromBuffer(const unsigned char* data, in
|
||||||
|
|
||||||
if (bytesLeftToRead >= (numberOfParticles * expectedBytesPerParticle)) {
|
if (bytesLeftToRead >= (numberOfParticles * expectedBytesPerParticle)) {
|
||||||
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
for (uint16_t i = 0; i < numberOfParticles; i++) {
|
||||||
int bytesForThisParticle = _particles[i].readParticleDataFromBuffer(dataAt, bytesLeftToRead, args);
|
Particle tempParticle;
|
||||||
|
int bytesForThisParticle = tempParticle.readParticleDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||||
|
_particles.push_back(tempParticle);
|
||||||
dataAt += bytesForThisParticle;
|
dataAt += bytesForThisParticle;
|
||||||
bytesLeftToRead -= bytesForThisParticle;
|
bytesLeftToRead -= bytesForThisParticle;
|
||||||
bytesRead += bytesForThisParticle;
|
bytesRead += bytesForThisParticle;
|
||||||
|
@ -105,5 +107,11 @@ bool ParticleTreeElement::collapseChildren() {
|
||||||
|
|
||||||
void ParticleTreeElement::storeParticle(const Particle& particle) {
|
void ParticleTreeElement::storeParticle(const Particle& particle) {
|
||||||
_particles.push_back(particle);
|
_particles.push_back(particle);
|
||||||
|
|
||||||
|
markWithChangedTime();
|
||||||
|
|
||||||
|
printf("ParticleTreeElement::storeParticle() element=%p _particles.size()=%ld particle.getPosition()=%f,%f,%f\n",
|
||||||
|
this, _particles.size(),
|
||||||
|
particle.getPosition().x, particle.getPosition().y, particle.getPosition().z);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,6 +69,8 @@ public:
|
||||||
/// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed.
|
/// shouldRender() state, the tree will remark elements as changed even in cases there the elements have not changed.
|
||||||
virtual bool isRendered() const { return getShouldRender(); }
|
virtual bool isRendered() const { return getShouldRender(); }
|
||||||
|
|
||||||
|
const std::vector<Particle>& getParticles() const { return _particles; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void storeParticle(const Particle& particle);
|
void storeParticle(const Particle& particle);
|
||||||
|
|
||||||
|
|
|
@ -50,6 +50,7 @@ Node::~Node() {
|
||||||
// Names of Node Types
|
// Names of Node Types
|
||||||
const char* NODE_TYPE_NAME_DOMAIN = "Domain";
|
const char* NODE_TYPE_NAME_DOMAIN = "Domain";
|
||||||
const char* NODE_TYPE_NAME_VOXEL_SERVER = "Voxel Server";
|
const char* NODE_TYPE_NAME_VOXEL_SERVER = "Voxel Server";
|
||||||
|
const char* NODE_TYPE_NAME_PARTICLE_SERVER = "Particle Server";
|
||||||
const char* NODE_TYPE_NAME_AGENT = "Agent";
|
const char* NODE_TYPE_NAME_AGENT = "Agent";
|
||||||
const char* NODE_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
|
const char* NODE_TYPE_NAME_AUDIO_MIXER = "Audio Mixer";
|
||||||
const char* NODE_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer";
|
const char* NODE_TYPE_NAME_AVATAR_MIXER = "Avatar Mixer";
|
||||||
|
@ -64,6 +65,8 @@ const char* Node::getTypeName() const {
|
||||||
return NODE_TYPE_NAME_DOMAIN;
|
return NODE_TYPE_NAME_DOMAIN;
|
||||||
case NODE_TYPE_VOXEL_SERVER:
|
case NODE_TYPE_VOXEL_SERVER:
|
||||||
return NODE_TYPE_NAME_VOXEL_SERVER;
|
return NODE_TYPE_NAME_VOXEL_SERVER;
|
||||||
|
case NODE_TYPE_PARTICLE_SERVER:
|
||||||
|
return NODE_TYPE_NAME_PARTICLE_SERVER;
|
||||||
case NODE_TYPE_AGENT:
|
case NODE_TYPE_AGENT:
|
||||||
return NODE_TYPE_NAME_AGENT;
|
return NODE_TYPE_NAME_AGENT;
|
||||||
case NODE_TYPE_AUDIO_MIXER:
|
case NODE_TYPE_AUDIO_MIXER:
|
||||||
|
|
Loading…
Reference in a new issue