diff --git a/assignment-client/src/octree/OctreeQueryNode.cpp b/assignment-client/src/octree/OctreeQueryNode.cpp index 35f8fb9973..56d5e041a9 100644 --- a/assignment-client/src/octree/OctreeQueryNode.cpp +++ b/assignment-client/src/octree/OctreeQueryNode.cpp @@ -325,8 +325,7 @@ void OctreeQueryNode::updateLastKnownViewFrustum() { } // save that we know the view has been sent. - quint64 now = usecTimestampNow(); - setLastTimeBagEmpty(now); // is this what we want? poor names + setLastTimeBagEmpty(); } diff --git a/assignment-client/src/octree/OctreeQueryNode.h b/assignment-client/src/octree/OctreeQueryNode.h index ea0f3240aa..ff59fb7685 100644 --- a/assignment-client/src/octree/OctreeQueryNode.h +++ b/assignment-client/src/octree/OctreeQueryNode.h @@ -77,7 +77,7 @@ public: bool moveShouldDump() const; quint64 getLastTimeBagEmpty() const { return _lastTimeBagEmpty; } - void setLastTimeBagEmpty(quint64 lastTimeBagEmpty) { _lastTimeBagEmpty = lastTimeBagEmpty; } + void setLastTimeBagEmpty() { _lastTimeBagEmpty = _sceneSendStartTime; } bool getCurrentPacketIsColor() const { return _currentPacketIsColor; } bool getCurrentPacketIsCompressed() const { return _currentPacketIsCompressed; } @@ -98,6 +98,8 @@ public: void setLastRootTimestamp(quint64 timestamp) { _lastRootTimestamp = timestamp; } unsigned int getlastOctreePacketLength() const { return _lastOctreePacketLength; } int getDuplicatePacketCount() const { return _duplicatePacketCount; } + + void sceneStart(quint64 sceneSendStartTime) { _sceneSendStartTime = sceneSendStartTime; } void nodeKilled(); void forceNodeShutdown(); @@ -158,6 +160,8 @@ private: SentPacketHistory _sentPacketHistory; QQueue _nackedSequenceNumbers; + + quint64 _sceneSendStartTime = 0; }; #endif // hifi_OctreeQueryNode_h diff --git a/assignment-client/src/octree/OctreeSendThread.cpp b/assignment-client/src/octree/OctreeSendThread.cpp index 2014c56476..d664fb5c8f 100644 --- a/assignment-client/src/octree/OctreeSendThread.cpp +++ b/assignment-client/src/octree/OctreeSendThread.cpp @@ -343,8 +343,7 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus if (!viewFrustumChanged && !nodeData->getWantDelta()) { // only set our last sent time if we weren't resetting due to frustum change - quint64 now = usecTimestampNow(); - nodeData->setLastTimeBagEmpty(now); + nodeData->setLastTimeBagEmpty(); } // track completed scenes and send out the stats packet accordingly @@ -368,9 +367,11 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus // TODO: add these to stats page //::startSceneSleepTime = _usleepTime; - + + nodeData->sceneStart(usecTimestampNow() - CHANGE_FUDGE); // start tracking our stats - nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); + nodeData->stats.sceneStarted(isFullScene, viewFrustumChanged, + _myServer->getOctree()->getRoot(), _myServer->getJurisdiction()); // This is the start of "resending" the scene. bool dontRestartSceneOnMove = false; // this is experimental @@ -561,6 +562,13 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus } + if (somethingToSend) { + qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval + << " maxPacketsPerInterval = " << maxPacketsPerInterval + << " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval; + } + + // Here's where we can/should allow the server to send other data... // send the environment packet // TODO: should we turn this into a while loop to better handle sending multiple special packets diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index a2ff71d010..7c214624c2 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -287,6 +287,18 @@ allSections.push(elWebSections); var elWebSourceURL = document.getElementById("property-web-source-url"); + var elParticleSections = document.querySelectorAll(".particle-section"); + allSections.push(elParticleSections); + var elParticleMaxParticles = document.getElementById("property-particle-maxparticles"); + var elParticleLifeSpan = document.getElementById("property-particle-lifespan"); + var elParticleEmitRate = document.getElementById("property-particle-emit-rate"); + var elParticleEmitDirectionX = document.getElementById("property-particle-emit-direction-x"); + var elParticleEmitDirectionY = document.getElementById("property-particle-emit-direction-y"); + var elParticleEmitDirectionZ = document.getElementById("property-particle-emit-direction-z"); + var elParticleEmitStrength = document.getElementById("property-particle-emit-strength"); + var elParticleLocalGravity = document.getElementById("property-particle-localgravity"); + var elParticleRadius = document.getElementById("property-particle-radius"); + var elTextSections = document.querySelectorAll(".text-section"); allSections.push(elTextSections); var elTextText = document.getElementById("property-text-text"); @@ -455,7 +467,7 @@ } } - if (properties.type == "Box" || properties.type == "Sphere") { + if (properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") { elColorSection.style.display = 'block'; elColorRed.value = properties.color.red; elColorGreen.value = properties.color.green; @@ -465,7 +477,7 @@ elColorSection.style.display = 'none'; } - if (properties.type == "Model") { + if (properties.type == "Model" || properties.type == "ParticleEffect") { for (var i = 0; i < elModelSections.length; i++) { elModelSections[i].style.display = 'block'; } @@ -479,7 +491,7 @@ elModelAnimationFrame.value = properties.animationFrameIndex; elModelAnimationSettings.value = properties.animationSettings; elModelTextures.value = properties.textures; - elModelOriginalTextures.value = properties.originalTextures; + elModelOriginalTextures.value = properties.originalTextures; } else if (properties.type == "Web") { for (var i = 0; i < elWebSections.length; i++) { elWebSections[i].style.display = 'block'; @@ -562,6 +574,20 @@ showElements(document.getElementsByClassName('skybox-section'), elZoneBackgroundMode.value == 'skybox'); showElements(document.getElementsByClassName('atmosphere-section'), elZoneBackgroundMode.value == 'atmosphere'); + } else if (properties.type == "ParticleEffect") { + for (var i = 0; i < elParticleSections.length; i++) { + elParticleSections[i].style.display = 'block'; + } + + elParticleMaxParticles.value = properties.maxParticles; + elParticleLifeSpan.value = properties.lifespan.toFixed(2); + elParticleEmitRate.value = properties.emitRate.toFixed(1); + elParticleEmitDirectionX.value = properties.emitDirection.x.toFixed(2); + elParticleEmitDirectionY.value = properties.emitDirection.y.toFixed(2); + elParticleEmitDirectionZ.value = properties.emitDirection.z.toFixed(2); + elParticleEmitStrength.value = properties.emitStrength.toFixed(2); + elParticleLocalGravity.value = properties.localGravity.toFixed(2); + elParticleRadius.value = properties.particleRadius.toFixed(3); } if (selected) { @@ -678,6 +704,18 @@ elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff')); elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl')); + + elParticleMaxParticles.addEventListener('change', createEmitNumberPropertyUpdateFunction('maxParticles')); + elParticleLifeSpan.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifespan')); + elParticleEmitRate.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitRate')); + var particleEmitDirectionChangeFunction = createEmitVec3PropertyUpdateFunctionWithMultiplier( + 'emitDirection', elParticleEmitDirectionX, elParticleEmitDirectionY, elParticleEmitDirectionZ, DEGREES_TO_RADIANS); + elParticleEmitDirectionX.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitDirectionY.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitDirectionZ.addEventListener('change', particleEmitDirectionChangeFunction); + elParticleEmitStrength.addEventListener('change', createEmitNumberPropertyUpdateFunction('emitStrength')); + elParticleLocalGravity.addEventListener('change', createEmitNumberPropertyUpdateFunction('localGravity')); + elParticleRadius.addEventListener('change', createEmitNumberPropertyUpdateFunction('particleRadius')); elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL')); elShapeType.addEventListener('change', createEmitTextPropertyUpdateFunction('shapeType')); @@ -1069,7 +1107,52 @@ - + +
+
Max Particles
+
+ +
+
+
+
Particle Life Span
+
+ +
+
+
+
Particle Emission Rate
+
+ +
+
+
+
Particle Emission Direction
+
+
X
+
Y
+
Z
+
+
+
+
Particle Emission Strength
+
+ +
+
+
+
Particle Local Gravity
+
+ +
+
+
+
Particle Radius
+
+ +
+
+
Model URL
diff --git a/examples/ajt-test.js b/examples/particles.js similarity index 100% rename from examples/ajt-test.js rename to examples/particles.js diff --git a/libraries/model/src/model/Geometry.cpp b/libraries/model/src/model/Geometry.cpp index 156f593421..ed0201763a 100755 --- a/libraries/model/src/model/Geometry.cpp +++ b/libraries/model/src/model/Geometry.cpp @@ -43,18 +43,18 @@ void Mesh::addAttribute(Slot slot, const BufferView& buffer) { } void Mesh::evalVertexFormat() { - VertexFormat vf; + auto vf = new VertexFormat(); int channelNum = 0; if (hasVertexData()) { - vf.setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0); + vf->setAttribute(gpu::Stream::POSITION, channelNum, _vertexBuffer._element, 0); channelNum++; } for (auto attrib : _attributeBuffers) { - vf.setAttribute(attrib.first, channelNum, attrib.second._element, 0); + vf->setAttribute(attrib.first, channelNum, attrib.second._element, 0); channelNum++; } - _vertexFormat = vf; + _vertexFormat.reset(vf); } void Mesh::setIndexBuffer(const BufferView& buffer) { @@ -112,12 +112,12 @@ const gpu::BufferStream Mesh::makeBufferStream() const { int channelNum = 0; if (hasVertexData()) { - stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat.getChannelStride(channelNum)); + stream.addBuffer(_vertexBuffer._buffer, _vertexBuffer._offset, _vertexFormat->getChannelStride(channelNum)); channelNum++; } for (auto attrib : _attributeBuffers) { BufferView& view = attrib.second; - stream.addBuffer(view._buffer, view._offset, _vertexFormat.getChannelStride(channelNum)); + stream.addBuffer(view._buffer, view._offset, _vertexFormat->getChannelStride(channelNum)); channelNum++; } diff --git a/libraries/model/src/model/Geometry.h b/libraries/model/src/model/Geometry.h index 31c06e6eca..95f1c3bce7 100755 --- a/libraries/model/src/model/Geometry.h +++ b/libraries/model/src/model/Geometry.h @@ -47,14 +47,14 @@ public: void setVertexBuffer(const BufferView& buffer); const BufferView& getVertexBuffer() const { return _vertexBuffer; } uint getNumVertices() const { return _vertexBuffer.getNumElements(); } - bool hasVertexData() const { return !_vertexBuffer._buffer; } + bool hasVertexData() const { return _vertexBuffer._buffer.get() != nullptr; } // Attribute Buffers int getNumAttributes() const { return _attributeBuffers.size(); } void addAttribute(Slot slot, const BufferView& buffer); // Stream format - const VertexFormat& getVertexFormat() const { return _vertexFormat; } + const gpu::Stream::FormatPointer getVertexFormat() const { return _vertexFormat; } // Index Buffer void setIndexBuffer(const BufferView& buffer); @@ -114,7 +114,7 @@ public: protected: - VertexFormat _vertexFormat; + gpu::Stream::FormatPointer _vertexFormat; BufferView _vertexBuffer; BufferViewMap _attributeBuffers; diff --git a/libraries/octree/src/OctreeConstants.h b/libraries/octree/src/OctreeConstants.h index 1246aeffd4..4a1baea2d5 100644 --- a/libraries/octree/src/OctreeConstants.h +++ b/libraries/octree/src/OctreeConstants.h @@ -34,9 +34,9 @@ const float VIEW_FRUSTUM_FOV_OVERSEND = 60.0f; // These are guards to prevent our voxel tree recursive routines from spinning out of control const int UNREASONABLY_DEEP_RECURSION = 29; // use this for something that you want to be shallow, but not spin out const int DANGEROUSLY_DEEP_RECURSION = 200; // use this for something that needs to go deeper -const float SCALE_AT_UNREASONABLY_DEEP_RECURSION = (1.0f / powf(2.0f, UNREASONABLY_DEEP_RECURSION)); -const float SCALE_AT_DANGEROUSLY_DEEP_RECURSION = (1.0f / powf(2.0f, DANGEROUSLY_DEEP_RECURSION)); -const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = SCALE_AT_UNREASONABLY_DEEP_RECURSION * 2.0f; // 0.00006103515 meter ~1/10,0000th +const float SCALE_AT_UNREASONABLY_DEEP_RECURSION = (TREE_SCALE / powf(2.0f, UNREASONABLY_DEEP_RECURSION)); +const float SCALE_AT_DANGEROUSLY_DEEP_RECURSION = (TREE_SCALE / powf(2.0f, DANGEROUSLY_DEEP_RECURSION)); +const float SMALLEST_REASONABLE_OCTREE_ELEMENT_SCALE = SCALE_AT_UNREASONABLY_DEEP_RECURSION * 2.0f; // 0.00001525878 meter ~1/10,0000th const int DEFAULT_MAX_OCTREE_PPS = 600; // the default maximum PPS we think any octree based server should send to a client