From 2400f5c00004f6397eeabf23b457de8ea3a416b6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 1 Jun 2015 09:02:59 -0700 Subject: [PATCH 01/43] update ALL parameters of remote physics simulation --- libraries/physics/src/EntityMotionState.cpp | 23 +++++++-------------- libraries/physics/src/EntityMotionState.h | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9a24aabb34..15be1da3ed 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -49,24 +49,17 @@ EntityMotionState::~EntityMotionState() { assert(!_entity); } -void EntityMotionState::updateServerPhysicsVariables(uint32_t flags) { - if (flags & EntityItem::DIRTY_POSITION) { - _serverPosition = _entity->getPosition(); - } - if (flags & EntityItem::DIRTY_ROTATION) { - _serverRotation = _entity->getRotation(); - } - if (flags & EntityItem::DIRTY_LINEAR_VELOCITY) { - _serverVelocity = _entity->getVelocity(); - } - if (flags & EntityItem::DIRTY_ANGULAR_VELOCITY) { - _serverAngularVelocity = _entity->getAngularVelocity(); - } +void EntityMotionState::updateServerPhysicsVariables() { + _serverPosition = _entity->getPosition(); + _serverRotation = _entity->getRotation(); + _serverVelocity = _entity->getVelocity(); + _serverAngularVelocity = _entity->getAngularVelocity(); + _serverAcceleration = _entity->getAcceleration(); } // virtual void EntityMotionState::handleEasyChanges(uint32_t flags) { - updateServerPhysicsVariables(flags); + updateServerPhysicsVariables(); ObjectMotionState::handleEasyChanges(flags); if (flags & EntityItem::DIRTY_SIMULATOR_ID) { _loopsWithoutOwner = 0; @@ -94,7 +87,7 @@ void EntityMotionState::handleEasyChanges(uint32_t flags) { // virtual void EntityMotionState::handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine) { - updateServerPhysicsVariables(flags); + updateServerPhysicsVariables(); ObjectMotionState::handleHardAndEasyChanges(flags, engine); } diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 65279dc01a..2be6d0490e 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -28,7 +28,7 @@ public: EntityMotionState(btCollisionShape* shape, EntityItemPointer item); virtual ~EntityMotionState(); - void updateServerPhysicsVariables(uint32_t flags); + void updateServerPhysicsVariables(); virtual void handleEasyChanges(uint32_t flags); virtual void handleHardAndEasyChanges(uint32_t flags, PhysicsEngine* engine); From fa491a5c4f013c0278d03199f5ff2339cb09919e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 1 Jun 2015 13:59:56 -0700 Subject: [PATCH 02/43] fix theoretical crash bug in editEntity() --- .../entities/src/EntityScriptingInterface.cpp | 43 ++++++++++--------- .../entities/src/EntityScriptingInterface.h | 2 +- 2 files changed, 23 insertions(+), 22 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index d684fbf2fc..36cc8dc07a 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -129,37 +129,38 @@ EntityItemProperties EntityScriptingInterface::getEntityProperties(QUuid identit return results; } -QUuid EntityScriptingInterface::editEntity(QUuid id, const EntityItemProperties& properties) { +QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties properties) { EntityItemID entityID(id); // If we have a local entity tree set, then also update it. if (_entityTree) { _entityTree->lockForWrite(); - _entityTree->updateEntity(entityID, properties); + bool updatedEntity = _entityTree->updateEntity(entityID, properties); _entityTree->unlock(); - } - // make sure the properties has a type, so that the encode can know which properties to include - if (properties.getType() == EntityTypes::Unknown) { - EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); - if (entity) { - // we need to change the outgoing properties, so we make a copy, modify, and send. - EntityItemProperties modifiedProperties = properties; - entity->setLastBroadcast(usecTimestampNow()); - modifiedProperties.setType(entity->getType()); - if (modifiedProperties.hasTerseUpdateChanges()) { - // we make a bid for (or assert) our simulation ownership - auto nodeList = DependencyManager::get(); - const QUuid myNodeID = nodeList->getSessionUUID(); - modifiedProperties.setSimulatorID(myNodeID); - - if (entity->getSimulatorID() == myNodeID) { - // we think we already own simulation, so make sure we send ALL TerseUpdate properties - entity->getAllTerseUpdateProperties(modifiedProperties); + if (updatedEntity) { + _entityTree->lockForRead(); + EntityItemPointer entity = _entityTree->findEntityByEntityItemID(entityID); + if (entity) { + // make sure the properties has a type, so that the encode can know which properties to include + properties.setType(entity->getType()); + if (properties.hasTerseUpdateChanges()) { + // we make a bid for (or assert) our simulation ownership + auto nodeList = DependencyManager::get(); + const QUuid myNodeID = nodeList->getSessionUUID(); + properties.setSimulatorID(myNodeID); + + if (entity->getSimulatorID() == myNodeID) { + // we think we already own the simulation, so make sure to send ALL TerseUpdate properties + entity->getAllTerseUpdateProperties(properties); + } } + entity->setLastBroadcast(usecTimestampNow()); } - queueEntityMessage(PacketTypeEntityEdit, entityID, modifiedProperties); + _entityTree->unlock(); + queueEntityMessage(PacketTypeEntityEdit, entityID, properties); return id; } + return QUuid(); } queueEntityMessage(PacketTypeEntityEdit, entityID, properties); diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index 6c2dc06579..0e2b27baad 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -78,7 +78,7 @@ public slots: /// edits a model updating only the included properties, will return the identified EntityItemID in case of /// successful edit, if the input entityID is for an unknown model this function will have no effect - Q_INVOKABLE QUuid editEntity(QUuid entityID, const EntityItemProperties& properties); + Q_INVOKABLE QUuid editEntity(QUuid entityID, EntityItemProperties properties); /// deletes a model Q_INVOKABLE void deleteEntity(QUuid entityID); From cc9ae81c7572397b1ac817f8a5578cfa16dc8bd0 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 1 Jun 2015 14:47:14 -0700 Subject: [PATCH 03/43] group Entity property settings together --- libraries/entities/src/EntityItem.cpp | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index cc951ac16b..d5dca268be 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -943,30 +943,37 @@ void EntityItem::getAllTerseUpdateProperties(EntityItemProperties& properties) c bool EntityItem::setProperties(const EntityItemProperties& properties) { bool somethingChanged = false; - SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePosition); // this will call recalculate collision shape if needed - SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensions); // NOTE: radius is obsolete + // these affect TerseUpdate properties + SET_ENTITY_PROPERTY_FROM_PROPERTIES(position, updatePosition); SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotation, updateRotation); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(velocity, updateVelocity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(acceleration, setAcceleration); + + // these (along with "position" above) affect tree structure + SET_ENTITY_PROPERTY_FROM_PROPERTIES(dimensions, updateDimensions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); + + // these (along with all properties above) affect the simulation + SET_ENTITY_PROPERTY_FROM_PROPERTIES(density, updateDensity); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(gravity, updateGravity); SET_ENTITY_PROPERTY_FROM_PROPERTIES(damping, updateDamping); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, updateAngularDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(restitution, updateRestitution); SET_ENTITY_PROPERTY_FROM_PROPERTIES(friction, updateFriction); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(lifetime, updateLifetime); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulatorID, updateSimulatorID); + + // non-simulation properties below SET_ENTITY_PROPERTY_FROM_PROPERTIES(script, setScript); SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionSoundURL, setCollisionSoundURL); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(registrationPoint, setRegistrationPoint); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularVelocity, updateAngularVelocity); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(angularDamping, updateAngularDamping); SET_ENTITY_PROPERTY_FROM_PROPERTIES(glowLevel, setGlowLevel); SET_ENTITY_PROPERTY_FROM_PROPERTIES(localRenderAlpha, setLocalRenderAlpha); SET_ENTITY_PROPERTY_FROM_PROPERTIES(visible, setVisible); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(ignoreForCollisions, updateIgnoreForCollisions); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionsWillMove, updateCollisionsWillMove); SET_ENTITY_PROPERTY_FROM_PROPERTIES(locked, setLocked); SET_ENTITY_PROPERTY_FROM_PROPERTIES(userData, setUserData); - SET_ENTITY_PROPERTY_FROM_PROPERTIES(simulatorID, updateSimulatorID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(marketplaceID, setMarketplaceID); SET_ENTITY_PROPERTY_FROM_PROPERTIES(name, setName); From acb3163f4306c59d5f4aba74897149cea87ce1d6 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Tue, 2 Jun 2015 17:20:41 -0700 Subject: [PATCH 04/43] add comments for future work --- libraries/entities/src/EntityScriptingInterface.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index c1c13a832c..5a897f7fe7 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -143,15 +143,22 @@ QUuid EntityScriptingInterface::editEntity(QUuid id, EntityItemProperties proper // make sure the properties has a type, so that the encode can know which properties to include properties.setType(entity->getType()); if (properties.hasTerseUpdateChanges()) { - // we make a bid for (or assert) our simulation ownership auto nodeList = DependencyManager::get(); const QUuid myNodeID = nodeList->getSessionUUID(); - properties.setSimulatorID(myNodeID); if (entity->getSimulatorID() == myNodeID) { // we think we already own the simulation, so make sure to send ALL TerseUpdate properties entity->getAllTerseUpdateProperties(properties); + // TODO: if we knew that ONLY TerseUpdate properties have changed in properties AND the object + // is dynamic AND it is active in the physics simulation then we could chose to NOT queue an update + // and instead let the physics simulation decide when to send a terse update. This would remove + // the "slide-no-rotate" glitch (and typical a double-update) that we see during the "poke rolling + // balls" test. However, even if we solve this problem we still need to provide a "slerp the visible + // proxy toward the true physical position" feature to hide the final glitches in the remote watcher's + // simulation. } + // we make a bid for (or assert existing) simulation ownership + properties.setSimulatorID(myNodeID); } entity->setLastBroadcast(usecTimestampNow()); } From bbf183779681e50e5b97ac984655238fa8ac8e94 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Jun 2015 16:14:23 +0200 Subject: [PATCH 05/43] Introduced RenderDetails/Stats don't pull details - Regrouped everything stat in a struct - Details are set into the stats --- interface/src/Application.cpp | 5 +- interface/src/avatar/Avatar.cpp | 2 +- interface/src/ui/Stats.cpp | 22 ++--- interface/src/ui/Stats.h | 5 +- interface/src/ui/overlays/Overlays.cpp | 2 +- .../src/EntityTreeRenderer.cpp | 26 +---- .../src/RenderableEntityItem.cpp | 2 +- .../src/RenderableModelEntityItem.cpp | 2 +- libraries/octree/src/OctreeRenderer.cpp | 17 ---- libraries/octree/src/OctreeRenderer.h | 34 ------- libraries/render-utils/src/Model.cpp | 32 +++---- libraries/render/src/render/DrawTask.cpp | 8 +- libraries/shared/src/RenderArgs.h | 94 +++++++------------ 13 files changed, 78 insertions(+), 173 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 76feb77076..3d2d4944ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -969,6 +969,7 @@ void Application::paintGL() { OculusManager::endFrameTiming(); } _frameCount++; + Stats::getInstance()->setRenderDetails(renderArgs._details); } void Application::runTests() { @@ -3491,7 +3492,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se _main3DScene->processPendingChangesQueue(); } - // FOr now every frame pass the renderCOntext + // For now every frame pass the renderContext { PerformanceTimer perfTimer("EngineRun"); render::RenderContext renderContext; @@ -3525,7 +3526,7 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se sceneInterface->setEngineFeedTransparentItems(engineRC->_numFeedTransparentItems); sceneInterface->setEngineDrawnTransparentItems(engineRC->_numDrawnTransparentItems); - + } diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 199c05af48..cd559eebda 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -74,7 +74,7 @@ namespace render { if (avatarPtr->isInitialized() && args) { avatarPtr->render(args, Application::getInstance()->getCamera()->getPosition()); - args->_elementsTouched++; + args->_details._elementsTouched++; } } } diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index c49208c835..5f3b67ab53 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -469,29 +469,29 @@ void Stats::display( // Model/Entity render details EntityTreeRenderer* entities = Application::getInstance()->getEntities(); octreeStats.str(""); - octreeStats << "Entity Items rendered: " << entities->getItemsRendered() - << " / Out of view:" << entities->getItemsOutOfView() - << " / Too small:" << entities->getItemsTooSmall(); + octreeStats << "Entity Items rendered: " << _renderDetails._itemsRendered + << " / Out of view:" << _renderDetails._itemsOutOfView + << " / Too small:" << _renderDetails._itemsTooSmall; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); if (_expanded) { octreeStats.str(""); - octreeStats << " Meshes rendered: " << entities->getMeshesRendered() - << " / Out of view:" << entities->getMeshesOutOfView() - << " / Too small:" << entities->getMeshesTooSmall(); + octreeStats << " Meshes rendered: " << _renderDetails._meshesRendered + << " / Out of view:" << _renderDetails._meshesOutOfView + << " / Too small:" << _renderDetails._meshesTooSmall; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); octreeStats.str(""); - octreeStats << " Triangles: " << entities->getTrianglesRendered() - << " / Quads:" << entities->getQuadsRendered() - << " / Material Switches:" << entities->getMaterialSwitches(); + octreeStats << " Triangles: " << _renderDetails._trianglesRendered + << " / Quads:" << _renderDetails._quadsRendered + << " / Material Switches:" << _renderDetails._materialSwitches; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); octreeStats.str(""); - octreeStats << " Mesh Parts Rendered Opaque: " << entities->getOpaqueMeshPartsRendered() - << " / Translucent:" << entities->getTranslucentMeshPartsRendered(); + octreeStats << " Mesh Parts Rendered Opaque: " << _renderDetails._opaqueMeshPartsRendered + << " / Translucent:" << _renderDetails._translucentMeshPartsRendered; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index 00c1650b71..4c6d6ede4e 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -14,7 +14,7 @@ #include -#include +#include class Stats: public QObject { Q_OBJECT @@ -35,6 +35,8 @@ public: int inKbitsPerSecond, int outKbitsPerSecond, int voxelPacketsToProcess); bool includeTimingRecord(const QString& name); + void setRenderDetails(const RenderDetails& details) { _renderDetails = details; } + private: static Stats* _sharedInstance; @@ -51,6 +53,7 @@ private: int _lastHorizontalOffset; + RenderDetails _renderDetails; }; #endif // hifi_Stats_h diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 5964596395..ad9817fce0 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -55,7 +55,7 @@ namespace render { } template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { if (args) { - args->_elementsTouched++; + args->_details._elementsTouched++; glPushMatrix(); if (overlay->getAnchor() == Overlay::MY_AVATAR) { diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index cc6693133f..ad0df484cc 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -531,24 +531,6 @@ void EntityTreeRenderer::render(RenderArgs* renderArgs) { // glPopMatrix(); renderArgs->_batch = nullptr; - - // stats... - _meshesConsidered = renderArgs->_meshesConsidered; - _meshesRendered = renderArgs->_meshesRendered; - _meshesOutOfView = renderArgs->_meshesOutOfView; - _meshesTooSmall = renderArgs->_meshesTooSmall; - - _elementsTouched = renderArgs->_elementsTouched; - _itemsRendered = renderArgs->_itemsRendered; - _itemsOutOfView = renderArgs->_itemsOutOfView; - _itemsTooSmall = renderArgs->_itemsTooSmall; - - _materialSwitches = renderArgs->_materialSwitches; - _trianglesRendered = renderArgs->_trianglesRendered; - _quadsRendered = renderArgs->_quadsRendered; - - _translucentMeshPartsRendered = renderArgs->_translucentMeshPartsRendered; - _opaqueMeshPartsRendered = renderArgs->_opaqueMeshPartsRendered; } deleteReleasedModels(); // seems like as good as any other place to do some memory cleanup } @@ -672,7 +654,7 @@ void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* arg } void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { - args->_elementsTouched++; + args->_details._elementsTouched++; // actually render it here... // we need to iterate the actual entityItems of the element EntityTreeElement* entityTreeElement = static_cast(element); @@ -737,15 +719,15 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) glower = new Glower(args, entityItem->getGlowLevel()); } entityItem->render(args); - args->_itemsRendered++; + args->_details._itemsRendered++; if (glower) { delete glower; } } else { - args->_itemsTooSmall++; + args->_details._itemsTooSmall++; } } else { - args->_itemsOutOfView++; + args->_details._itemsOutOfView++; } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 926889ccac..2d04628e5c 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -30,7 +30,7 @@ namespace render { } template <> void payloadRender(const RenderableEntityItemProxy::Pointer& payload, RenderArgs* args) { if (args) { - args->_elementsTouched++; + args->_details._elementsTouched++; if (payload && payload->entity) { if (payload->entity->getType() != EntityTypes::Model) { payload->entity->render(args); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index c4930f1225..e22bc4a137 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -159,7 +159,7 @@ namespace render { } template <> void payloadRender(const RenderableModelEntityItemMeta::Pointer& payload, RenderArgs* args) { if (args) { - args->_elementsTouched++; + args->_details._elementsTouched++; if (payload && payload->entity) { payload->entity->render(args); } diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index 246fab8578..7852f1d4b4 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -171,23 +171,6 @@ void OctreeRenderer::render(RenderArgs* renderArgs) { _tree->recurseTreeWithOperation(renderOperation, renderArgs); _tree->unlock(); } - _meshesConsidered = renderArgs->_meshesConsidered; - _meshesRendered = renderArgs->_meshesRendered; - _meshesOutOfView = renderArgs->_meshesOutOfView; - _meshesTooSmall = renderArgs->_meshesTooSmall; - - _elementsTouched = renderArgs->_elementsTouched; - _itemsRendered = renderArgs->_itemsRendered; - _itemsOutOfView = renderArgs->_itemsOutOfView; - _itemsTooSmall = renderArgs->_itemsTooSmall; - - _materialSwitches = renderArgs->_materialSwitches; - _trianglesRendered = renderArgs->_trianglesRendered; - _quadsRendered = renderArgs->_quadsRendered; - - _translucentMeshPartsRendered = renderArgs->_translucentMeshPartsRendered; - _opaqueMeshPartsRendered = renderArgs->_opaqueMeshPartsRendered; - } void OctreeRenderer::clear() { diff --git a/libraries/octree/src/OctreeRenderer.h b/libraries/octree/src/OctreeRenderer.h index 3172d3429d..98026b732c 100644 --- a/libraries/octree/src/OctreeRenderer.h +++ b/libraries/octree/src/OctreeRenderer.h @@ -60,23 +60,6 @@ public: /// clears the tree virtual void clear(); - - int getElementsTouched() const { return _elementsTouched; } - int getItemsRendered() const { return _itemsRendered; } - int getItemsOutOfView() const { return _itemsOutOfView; } - int getItemsTooSmall() const { return _itemsTooSmall; } - - int getMeshesConsidered() const { return _meshesConsidered; } - int getMeshesRendered() const { return _meshesRendered; } - int getMeshesOutOfView() const { return _meshesOutOfView; } - int getMeshesTooSmall() const { return _meshesTooSmall; } - - int getMaterialSwitches() const { return _materialSwitches; } - int getTrianglesRendered() const { return _trianglesRendered; } - int getQuadsRendered() const { return _quadsRendered; } - - int getTranslucentMeshPartsRendered() const { return _translucentMeshPartsRendered; } - int getOpaqueMeshPartsRendered() const { return _opaqueMeshPartsRendered; } protected: virtual Octree* createTree() = 0; @@ -84,23 +67,6 @@ protected: Octree* _tree; bool _managedTree; ViewFrustum* _viewFrustum; - - int _elementsTouched; - int _itemsRendered; - int _itemsOutOfView; - int _itemsTooSmall; - - int _meshesConsidered; - int _meshesRendered; - int _meshesOutOfView; - int _meshesTooSmall; - - int _materialSwitches; - int _trianglesRendered; - int _quadsRendered; - - int _translucentMeshPartsRendered; - int _opaqueMeshPartsRendered; }; #endif // hifi_OctreeRenderer_h diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 312890a188..ab2a6568cf 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -834,7 +834,7 @@ namespace render { } template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - args->_elementsTouched++; + args->_details._elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } } @@ -866,7 +866,7 @@ namespace render { } template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - args->_elementsTouched++; + args->_details._elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } } @@ -1121,8 +1121,8 @@ bool Model::renderCore(RenderArgs* args, float alpha) { _viewState->setupWorldLight(); if (args) { - args->_translucentMeshPartsRendered = translucentMeshPartsRendered; - args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; + args->_details._translucentMeshPartsRendered = translucentMeshPartsRendered; + args->_details._opaqueMeshPartsRendered = opaqueMeshPartsRendered; } #ifdef WANT_DEBUG_MESHBOXES @@ -2192,8 +2192,8 @@ void Model::endScene(RenderArgs* args) { GLBATCH(glUseProgram)(0); if (args) { - args->_translucentMeshPartsRendered = translucentParts; - args->_opaqueMeshPartsRendered = opaqueMeshPartsRendered; + args->_details._translucentMeshPartsRendered = translucentParts; + args->_details._opaqueMeshPartsRendered = opaqueMeshPartsRendered; } } @@ -2430,7 +2430,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran } if (args) { - args->_materialSwitches++; + args->_details._materialSwitches++; } // HACK: For unknown reason (yet!) this code that should be assigned only if the material changes need to be called for every @@ -2463,8 +2463,8 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (args) { const int INDICES_PER_TRIANGLE = 3; const int INDICES_PER_QUAD = 4; - args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } } @@ -2683,7 +2683,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // if we got here, then check to see if this mesh is in view if (args) { bool shouldRender = true; - args->_meshesConsidered++; + args->_details._meshesConsidered++; if (args->_viewFrustum) { @@ -2695,15 +2695,15 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); if (!shouldRender) { - args->_meshesTooSmall++; + args->_details._meshesTooSmall++; } } else { - args->_meshesOutOfView++; + args->_details._meshesOutOfView++; } } if (shouldRender) { - args->_meshesRendered++; + args->_details._meshesRendered++; } else { continue; // skip this mesh } @@ -2797,7 +2797,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (args) { - args->_materialSwitches++; + args->_details._materialSwitches++; } } @@ -2833,8 +2833,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (args) { const int INDICES_PER_TRIANGLE = 3; const int INDICES_PER_QUAD = 4; - args->_trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index dd57a71fcf..9115fc73ef 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -71,7 +71,7 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont if (bound.isNull()) { outItems.push_back(id); // One more Item to render - args->_itemsRendered++; + args->_details._itemsRendered++; continue; } @@ -83,12 +83,12 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont if (bigEnoughToRender) { outItems.push_back(id); // One more Item to render - args->_itemsRendered++; + args->_details._itemsRendered++; } else { - args->_itemsTooSmall++; + args->_details._itemsTooSmall++; } } else { - args->_itemsOutOfView++; + args->_details._itemsOutOfView++; } } } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index aefaca8a31..0cf8aa5799 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -22,6 +22,25 @@ class Batch; class Context; } +struct RenderDetails { + int _elementsTouched = 0; + int _itemsRendered = 0; + int _itemsOutOfView = 0; + int _itemsTooSmall = 0; + + int _meshesConsidered = 0; + int _meshesRendered = 0; + int _meshesOutOfView = 0; + int _meshesTooSmall = 0; + + int _materialSwitches = 0; + int _trianglesRendered = 0; + int _quadsRendered = 0; + + int _translucentMeshPartsRendered = 0; + int _opaqueMeshPartsRendered = 0; +}; + class RenderArgs { public: typedef std::function ShoudRenderFunctor; @@ -45,24 +64,7 @@ public: RenderSide renderSide = MONO, DebugFlags debugFlags = RENDER_DEBUG_NONE, gpu::Batch* batch = nullptr, - ShoudRenderFunctor shouldRender = nullptr, - - int elementsTouched = 0, - int itemsRendered = 0, - int itemsOutOfView = 0, - int itemsTooSmall = 0, - - int meshesConsidered = 0, - int meshesRendered = 0, - int meshesOutOfView = 0, - int meshesTooSmall = 0, - - int materialSwitches = 0, - int trianglesRendered = 0, - int quadsRendered = 0, - - int translucentMeshPartsRendered = 0, - int opaqueMeshPartsRendered = 0) : + ShoudRenderFunctor shouldRender = nullptr) : _context(context), _renderer(renderer), _viewFrustum(viewFrustum), @@ -72,53 +74,21 @@ public: _renderSide(renderSide), _debugFlags(debugFlags), _batch(batch), - _shouldRender(shouldRender), - - _elementsTouched(elementsTouched), - _itemsRendered(itemsRendered), - _itemsOutOfView(itemsOutOfView), - _itemsTooSmall(itemsTooSmall), - - _meshesConsidered(meshesConsidered), - _meshesRendered(meshesRendered), - _meshesOutOfView(meshesOutOfView), - _meshesTooSmall(meshesTooSmall), - - _materialSwitches(materialSwitches), - _trianglesRendered(trianglesRendered), - _quadsRendered(quadsRendered), - - _translucentMeshPartsRendered(translucentMeshPartsRendered), - _opaqueMeshPartsRendered(opaqueMeshPartsRendered) { + _shouldRender(shouldRender) { } - gpu::Context* _context; - OctreeRenderer* _renderer; - ViewFrustum* _viewFrustum; - float _sizeScale; - int _boundaryLevelAdjust; - RenderMode _renderMode; - RenderSide _renderSide; - DebugFlags _debugFlags; - gpu::Batch* _batch; + gpu::Context* _context = nullptr; + OctreeRenderer* _renderer = nullptr; + ViewFrustum* _viewFrustum = nullptr; + float _sizeScale = 1.0f; + int _boundaryLevelAdjust = 0; + RenderMode _renderMode = DEFAULT_RENDER_MODE; + RenderSide _renderSide = MONO; + DebugFlags _debugFlags = RENDER_DEBUG_NONE; + gpu::Batch* _batch = nullptr; ShoudRenderFunctor _shouldRender; - - int _elementsTouched; - int _itemsRendered; - int _itemsOutOfView; - int _itemsTooSmall; - - int _meshesConsidered; - int _meshesRendered; - int _meshesOutOfView; - int _meshesTooSmall; - - int _materialSwitches; - int _trianglesRendered; - int _quadsRendered; - - int _translucentMeshPartsRendered; - int _opaqueMeshPartsRendered; + + RenderDetails _details; float _alphaThreshold = 0.5f; }; From 9df1b051844841cb0e66af3f0c18d8ae46cb8602 Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Wed, 3 Jun 2015 18:08:43 +0200 Subject: [PATCH 06/43] Introduce outsideEngineDetails --- interface/src/avatar/Avatar.cpp | 1 - interface/src/ui/overlays/Overlays.cpp | 2 -- .../src/EntityTreeRenderer.cpp | 8 +++---- .../src/RenderableEntityItem.cpp | 1 - .../src/RenderableModelEntityItem.cpp | 1 - libraries/render-utils/src/Model.cpp | 24 +++++++++---------- libraries/render/src/render/DrawTask.cpp | 6 +++-- libraries/shared/src/RenderArgs.h | 1 + 8 files changed, 20 insertions(+), 24 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index cd559eebda..a88e757d28 100644 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -74,7 +74,6 @@ namespace render { if (avatarPtr->isInitialized() && args) { avatarPtr->render(args, Application::getInstance()->getCamera()->getPosition()); - args->_details._elementsTouched++; } } } diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index ad9817fce0..311b0be867 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -55,8 +55,6 @@ namespace render { } template <> void payloadRender(const Overlay::Pointer& overlay, RenderArgs* args) { if (args) { - args->_details._elementsTouched++; - glPushMatrix(); if (overlay->getAnchor() == Overlay::MY_AVATAR) { MyAvatar* avatar = DependencyManager::get()->getMyAvatar(); diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index ad0df484cc..02a3747cec 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -654,7 +654,7 @@ void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* arg } void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { - args->_details._elementsTouched++; + args->_outsideEngineDetails._elementsTouched++; // actually render it here... // we need to iterate the actual entityItems of the element EntityTreeElement* entityTreeElement = static_cast(element); @@ -719,15 +719,15 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) glower = new Glower(args, entityItem->getGlowLevel()); } entityItem->render(args); - args->_details._itemsRendered++; + args->_outsideEngineDetails._itemsRendered++; if (glower) { delete glower; } } else { - args->_details._itemsTooSmall++; + args->_outsideEngineDetails._itemsTooSmall++; } } else { - args->_details._itemsOutOfView++; + args->_outsideEngineDetails._itemsOutOfView++; } } } diff --git a/libraries/entities-renderer/src/RenderableEntityItem.cpp b/libraries/entities-renderer/src/RenderableEntityItem.cpp index 2d04628e5c..144740f95d 100644 --- a/libraries/entities-renderer/src/RenderableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableEntityItem.cpp @@ -30,7 +30,6 @@ namespace render { } template <> void payloadRender(const RenderableEntityItemProxy::Pointer& payload, RenderArgs* args) { if (args) { - args->_details._elementsTouched++; if (payload && payload->entity) { if (payload->entity->getType() != EntityTypes::Model) { payload->entity->render(args); diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index e22bc4a137..98a9fd0bd6 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -159,7 +159,6 @@ namespace render { } template <> void payloadRender(const RenderableModelEntityItemMeta::Pointer& payload, RenderArgs* args) { if (args) { - args->_details._elementsTouched++; if (payload && payload->entity) { payload->entity->render(args); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ab2a6568cf..6f4b9bca9e 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -834,7 +834,6 @@ namespace render { } template <> void payloadRender(const TransparentMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - args->_details._elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, true); } } @@ -866,7 +865,6 @@ namespace render { } template <> void payloadRender(const OpaqueMeshPart::Pointer& payload, RenderArgs* args) { if (args) { - args->_details._elementsTouched++; return payload->model->renderPart(args, payload->meshIndex, payload->partIndex, false); } } @@ -1121,8 +1119,8 @@ bool Model::renderCore(RenderArgs* args, float alpha) { _viewState->setupWorldLight(); if (args) { - args->_details._translucentMeshPartsRendered = translucentMeshPartsRendered; - args->_details._opaqueMeshPartsRendered = opaqueMeshPartsRendered; + args->_outsideEngineDetails._translucentMeshPartsRendered = translucentMeshPartsRendered; + args->_outsideEngineDetails._opaqueMeshPartsRendered = opaqueMeshPartsRendered; } #ifdef WANT_DEBUG_MESHBOXES @@ -2192,8 +2190,8 @@ void Model::endScene(RenderArgs* args) { GLBATCH(glUseProgram)(0); if (args) { - args->_details._translucentMeshPartsRendered = translucentParts; - args->_details._opaqueMeshPartsRendered = opaqueMeshPartsRendered; + args->_outsideEngineDetails._translucentMeshPartsRendered = translucentParts; + args->_outsideEngineDetails._opaqueMeshPartsRendered = opaqueMeshPartsRendered; } } @@ -2683,7 +2681,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // if we got here, then check to see if this mesh is in view if (args) { bool shouldRender = true; - args->_details._meshesConsidered++; + args->_outsideEngineDetails._meshesConsidered++; if (args->_viewFrustum) { @@ -2695,15 +2693,15 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); if (!shouldRender) { - args->_details._meshesTooSmall++; + args->_outsideEngineDetails._meshesTooSmall++; } } else { - args->_details._meshesOutOfView++; + args->_outsideEngineDetails._meshesOutOfView++; } } if (shouldRender) { - args->_details._meshesRendered++; + args->_outsideEngineDetails._meshesRendered++; } else { continue; // skip this mesh } @@ -2797,7 +2795,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod } if (args) { - args->_details._materialSwitches++; + args->_outsideEngineDetails._materialSwitches++; } } @@ -2833,8 +2831,8 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (args) { const int INDICES_PER_TRIANGLE = 3; const int INDICES_PER_QUAD = 4; - args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + args->_outsideEngineDetails._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; + args->_outsideEngineDetails._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; } } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 9115fc73ef..ec8c8d055f 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -63,6 +63,8 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; + + int startingSize = outItems.size(); // Culling / LOD for (auto id : inItems) { @@ -71,7 +73,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont if (bound.isNull()) { outItems.push_back(id); // One more Item to render - args->_details._itemsRendered++; continue; } @@ -83,7 +84,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont if (bigEnoughToRender) { outItems.push_back(id); // One more Item to render - args->_details._itemsRendered++; } else { args->_details._itemsTooSmall++; } @@ -91,6 +91,8 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont args->_details._itemsOutOfView++; } } + + args->_details._itemsRendered += (outItems.size() - startingSize); } struct ItemBound { diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 0cf8aa5799..1bce99907c 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -89,6 +89,7 @@ public: ShoudRenderFunctor _shouldRender; RenderDetails _details; + RenderDetails _outsideEngineDetails; float _alphaThreshold = 0.5f; }; From c036b5fd4ba759a574e24d0463d3f75b16518497 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 3 Jun 2015 10:19:28 -0700 Subject: [PATCH 07/43] Actually commit the changes this time! --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 9 +++++++-- libraries/physics/src/EntityMotionState.cpp | 7 +++++++ libraries/physics/src/EntityMotionState.h | 2 ++ libraries/physics/src/ObjectMotionState.cpp | 3 +++ libraries/physics/src/ObjectMotionState.h | 1 + libraries/physics/src/PhysicsEngine.cpp | 6 ++++-- libraries/shared/src/RegisteredMetaTypes.h | 8 +++++--- 7 files changed, 29 insertions(+), 7 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 23e504bfb8..5e88eae17a 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1131,10 +1131,15 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT } const float mass = entity->computeMass(); const float COLLISION_PENTRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity() - const float linearVelocity = glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY; + // The collision.penetration is a pretty good indicator of changed velocity AFTER the initial contact, + // but that first contact depends on exactly where we hit in the physics step. + // We can get a more consistent initial-contact energy reading by using the changed velocity. + const float linearVelocity = (collision.type == CONTACT_EVENT_TYPE_START) ? + glm::length(collision.velocityChange) : + glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY; const float energy = mass * linearVelocity * linearVelocity / 2.0f; const glm::vec3 position = collision.contactPoint; - const float COLLISION_ENERGY_AT_FULL_VOLUME = 0.5f; + const float COLLISION_ENERGY_AT_FULL_VOLUME = (collision.type == CONTACT_EVENT_TYPE_START) ? 10.0f : 0.5f; const float COLLISION_MINIMUM_VOLUME = 0.005f; const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME); if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) { diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9a24aabb34..1f5a1b9f4e 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -494,6 +494,7 @@ void EntityMotionState::measureBodyAcceleration() { float dt = ((float)numSubsteps * PHYSICS_ENGINE_FIXED_SUBSTEP); float invDt = 1.0f / dt; _lastMeasureStep = thisStep; + _measuredDeltaTime = dt; // Note: the integration equation for velocity uses damping: v1 = (v0 + a * dt) * (1 - D)^dt // hence the equation for acceleration is: a = (v1 / (1 - D)^dt - v0) / dt @@ -502,6 +503,12 @@ void EntityMotionState::measureBodyAcceleration() { _lastVelocity = velocity; } } +glm::vec3 EntityMotionState::getObjectLinearVelocityChange() const { + // This is the dampened change in linear velocity, as calculated in measureBodyAcceleration: dv = a * dt + // It is generally only meaningful during the lifespan of collision. In particular, it is not meaningful + // when the entity first starts moving via direct user action. + return _measuredAcceleration * _measuredDeltaTime; +} // virtual void EntityMotionState::setMotionType(MotionType motionType) { diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 65279dc01a..b38254d42c 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -64,6 +64,7 @@ public: virtual glm::vec3 getObjectLinearVelocity() const { return _entity->getVelocity(); } virtual glm::vec3 getObjectAngularVelocity() const { return _entity->getAngularVelocity(); } virtual glm::vec3 getObjectGravity() const { return _entity->getGravity(); } + virtual glm::vec3 getObjectLinearVelocityChange() const; virtual const QUuid& getObjectID() const { return _entity->getID(); } @@ -101,6 +102,7 @@ protected: uint32_t _lastMeasureStep; glm::vec3 _lastVelocity; glm::vec3 _measuredAcceleration; + float _measuredDeltaTime; quint8 _accelerationNearlyGravityCount; bool _candidateForOwnership; diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 57b75f0f3b..67dc8f294c 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -82,6 +82,9 @@ void ObjectMotionState::setBodyGravity(const glm::vec3& gravity) const { glm::vec3 ObjectMotionState::getBodyLinearVelocity() const { return bulletToGLM(_body->getLinearVelocity()); } +glm::vec3 ObjectMotionState::getObjectLinearVelocityChange() const { + return glm::vec3(); // Subclasses override where meaningful. +} glm::vec3 ObjectMotionState::getBodyAngularVelocity() const { return bulletToGLM(_body->getAngularVelocity()); diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 246ed16627..141fbe252b 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -90,6 +90,7 @@ public: glm::vec3 getBodyLinearVelocity() const; glm::vec3 getBodyAngularVelocity() const; + virtual glm::vec3 getObjectLinearVelocityChange() const; virtual uint32_t getAndClearIncomingDirtyFlags() = 0; diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index b622a37136..7b9f499925 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -317,6 +317,8 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() { if(type != CONTACT_EVENT_TYPE_CONTINUE || _numSubsteps % CONTINUE_EVENT_FILTER_FREQUENCY == 0) { ObjectMotionState* A = static_cast(contactItr->first._a); ObjectMotionState* B = static_cast(contactItr->first._b); + glm::vec3 velocityChange = (A ? A->getObjectLinearVelocityChange() : glm::vec3(0.0f)) + + (B ? B->getObjectLinearVelocityChange() : glm::vec3(0.0f)); if (A && A->getType() == MOTIONSTATE_TYPE_ENTITY) { QUuid idA = A->getObjectID(); @@ -326,14 +328,14 @@ CollisionEvents& PhysicsEngine::getCollisionEvents() { } glm::vec3 position = bulletToGLM(contact.getPositionWorldOnB()) + _originOffset; glm::vec3 penetration = bulletToGLM(contact.distance * contact.normalWorldOnB); - _collisionEvents.push_back(Collision(type, idA, idB, position, penetration)); + _collisionEvents.push_back(Collision(type, idA, idB, position, penetration, velocityChange)); } else if (B && B->getType() == MOTIONSTATE_TYPE_ENTITY) { QUuid idB = B->getObjectID(); glm::vec3 position = bulletToGLM(contact.getPositionWorldOnA()) + _originOffset; // NOTE: we're flipping the order of A and B (so that the first objectID is never NULL) // hence we must negate the penetration. glm::vec3 penetration = - bulletToGLM(contact.distance * contact.normalWorldOnB); - _collisionEvents.push_back(Collision(type, idB, QUuid(), position, penetration)); + _collisionEvents.push_back(Collision(type, idB, QUuid(), position, penetration, velocityChange)); } } diff --git a/libraries/shared/src/RegisteredMetaTypes.h b/libraries/shared/src/RegisteredMetaTypes.h index 48eecba227..1dcc85107a 100644 --- a/libraries/shared/src/RegisteredMetaTypes.h +++ b/libraries/shared/src/RegisteredMetaTypes.h @@ -78,15 +78,17 @@ enum ContactEventType { class Collision { public: - Collision() : type(CONTACT_EVENT_TYPE_START), idA(), idB(), contactPoint(0.0f), penetration(0.0f) { } - Collision(ContactEventType cType, const QUuid& cIdA, const QUuid& cIdB, const glm::vec3& cPoint, const glm::vec3& cPenetration) - : type(cType), idA(cIdA), idB(cIdB), contactPoint(cPoint), penetration(cPenetration) { } + Collision() : type(CONTACT_EVENT_TYPE_START), idA(), idB(), contactPoint(0.0f), penetration(0.0f), velocityChange(0.0f) { } + Collision(ContactEventType cType, const QUuid& cIdA, const QUuid& cIdB, const glm::vec3& cPoint, + const glm::vec3& cPenetration, const glm::vec3& velocityChange) + : type(cType), idA(cIdA), idB(cIdB), contactPoint(cPoint), penetration(cPenetration), velocityChange(velocityChange) { } ContactEventType type; QUuid idA; QUuid idB; glm::vec3 contactPoint; glm::vec3 penetration; + glm::vec3 velocityChange; }; Q_DECLARE_METATYPE(Collision) QScriptValue collisionToScriptValue(QScriptEngine* engine, const Collision& collision); From 407746b842b7c3d2aaf01d7cc5ee23962425d58c Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Wed, 3 Jun 2015 10:38:20 -0700 Subject: [PATCH 08/43] Fix (consistent) typo in non-magic-number constant's name. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 5e88eae17a..93e302c81b 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1130,13 +1130,13 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT return; } const float mass = entity->computeMass(); - const float COLLISION_PENTRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity() + const float COLLISION_PENETRATION_TO_VELOCITY = 50; // as a subsitute for RELATIVE entity->getVelocity() // The collision.penetration is a pretty good indicator of changed velocity AFTER the initial contact, // but that first contact depends on exactly where we hit in the physics step. // We can get a more consistent initial-contact energy reading by using the changed velocity. const float linearVelocity = (collision.type == CONTACT_EVENT_TYPE_START) ? glm::length(collision.velocityChange) : - glm::length(collision.penetration) * COLLISION_PENTRATION_TO_VELOCITY; + glm::length(collision.penetration) * COLLISION_PENETRATION_TO_VELOCITY; const float energy = mass * linearVelocity * linearVelocity / 2.0f; const glm::vec3 position = collision.contactPoint; const float COLLISION_ENERGY_AT_FULL_VOLUME = (collision.type == CONTACT_EVENT_TYPE_START) ? 10.0f : 0.5f; From 7b6cc59d305379e3918c40de2e4cf003a6fcaf1f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 11:40:48 -0700 Subject: [PATCH 09/43] basic support for collision groups --- interface/src/avatar/AvatarMotionState.cpp | 6 ++ interface/src/avatar/AvatarMotionState.h | 2 + .../src/DynamicCharacterController.cpp | 3 +- libraries/physics/src/EntityMotionState.cpp | 5 ++ libraries/physics/src/EntityMotionState.h | 2 + libraries/physics/src/ObjectMotionState.h | 2 + libraries/physics/src/PhysicsEngine.cpp | 25 +++++++- libraries/physics/src/PhysicsEngine.h | 59 +++++++++++++++++++ 8 files changed, 100 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 530225b319..7a5fb5662c 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -10,6 +10,7 @@ // #include +#include #include "Avatar.h" #include "AvatarMotionState.h" @@ -151,6 +152,11 @@ QUuid AvatarMotionState::getSimulatorID() const { void AvatarMotionState::bump() { } +// virtual +int16_t AvatarMotionState::computeCollisionGroup() { + return COLLISION_GROUP_OTHER_AVATAR; +} + // virtual void AvatarMotionState::clearObjectBackPointer() { ObjectMotionState::clearObjectBackPointer(); diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 68c687d65b..79a4d23179 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -61,6 +61,8 @@ public: void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } + virtual int16_t computeCollisionGroup(); + friend class AvatarManager; protected: diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index 5d2a1798f9..b55975c11a 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -5,6 +5,7 @@ #include "BulletUtil.h" #include "DynamicCharacterController.h" +#include "PhysicsEngine.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float DEFAULT_GRAVITY = -5.0f; @@ -267,7 +268,7 @@ void DynamicCharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (world && _rigidBody) { _dynamicsWorld = world; _pendingFlags &= ~ PENDING_FLAG_JUMP; - _dynamicsWorld->addRigidBody(_rigidBody); + _dynamicsWorld->addRigidBody(_rigidBody, COLLISION_GROUP_MY_AVATAR, COLLISION_MASK_MY_AVATAR); _dynamicsWorld->addAction(this); //reset(_dynamicsWorld); } diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9a24aabb34..c7cbca7ea7 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -517,3 +517,8 @@ QString EntityMotionState::getName() { } return ""; } + +// virtual +int16_t EntityMotionState::computeCollisionGroup() { + return COLLISION_GROUP_DEFAULT; +} diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 65279dc01a..da1a5b5d81 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -77,6 +77,8 @@ public: virtual QString getName(); + virtual int16_t computeCollisionGroup(); + friend class PhysicalEntitySimulation; protected: diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 246ed16627..fc0c58b5da 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -123,6 +123,8 @@ public: virtual QString getName() { return ""; } + virtual int16_t computeCollisionGroup() = 0; + friend class PhysicsEngine; protected: diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index b622a37136..5d6823c403 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -23,8 +23,19 @@ uint32_t PhysicsEngine::getNumSubsteps() { } PhysicsEngine::PhysicsEngine(const glm::vec3& offset) : - _originOffset(offset), - _characterController(nullptr) { + _originOffset(offset), + _characterController(nullptr) { + // build table of masks with their group as the key + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEFAULT), COLLISION_MASK_DEFAULT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_STATIC), COLLISION_MASK_STATIC); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_KINEMATIC), COLLISION_MASK_KINEMATIC); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_DEBRIS), COLLISION_MASK_DEBRIS); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_TRIGGER), COLLISION_MASK_TRIGGER); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_AVATAR), COLLISION_MASK_MY_AVATAR); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_MY_ATTACHMENT), COLLISION_MASK_MY_ATTACHMENT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_AVATAR), COLLISION_MASK_OTHER_AVATAR); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_OTHER_ATTACHMENT), COLLISION_MASK_OTHER_ATTACHMENT); + _collisionMasks.insert(btHashInt((int)COLLISION_GROUP_COLLISIONLESS), COLLISION_MASK_COLLISIONLESS); } PhysicsEngine::~PhysicsEngine() { @@ -125,7 +136,8 @@ void PhysicsEngine::addObject(ObjectMotionState* motionState) { body->setFlags(BT_DISABLE_WORLD_GRAVITY); motionState->updateBodyMaterialProperties(); - _dynamicsWorld->addRigidBody(body); + int16_t group = motionState->computeCollisionGroup(); + _dynamicsWorld->addRigidBody(body, group, getCollisionMask(group)); motionState->getAndClearIncomingDirtyFlags(); } @@ -417,6 +429,7 @@ void PhysicsEngine::setCharacterController(DynamicCharacterController* character } } +// static bool PhysicsEngine::physicsInfoIsActive(void* physicsInfo) { if (!physicsInfo) { return false; @@ -431,6 +444,7 @@ bool PhysicsEngine::physicsInfoIsActive(void* physicsInfo) { return body->isActive(); } +// static bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn) { if (!physicsInfo) { return false; @@ -448,3 +462,8 @@ bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn return true; } + +int16_t PhysicsEngine::getCollisionMask(int16_t group) const { + const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); + return mask ? *mask : COLLISION_MASK_DEFAULT; +} diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index 9ff85c9f11..f0bd8ba4e9 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -25,6 +25,61 @@ #include "ObjectMotionState.h" #include "ThreadSafeDynamicsWorld.h" +/* Note: These are the collision groups defined in btBroadphaseProxy. Only + * DefaultFilter and StaticFilter are explicitly used by Bullet (when the + * collision filter of an object is not manually specified), the rest are + * merely suggestions. + * +enum CollisionFilterGroups { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + CharacterFilter = 32, + AllFilter = -1 +} + * + * When using custom collision filters we pretty much need to do all or nothing. + * We'll be doing it all which means we define our own groups and build custom masks + * for everything. + * +*/ + +const int16_t COLLISION_GROUP_DEFAULT = 1 << 0; +const int16_t COLLISION_GROUP_STATIC = 1 << 1; +const int16_t COLLISION_GROUP_KINEMATIC = 1 << 2; +const int16_t COLLISION_GROUP_DEBRIS = 1 << 3; +const int16_t COLLISION_GROUP_TRIGGER = 1 << 4; +const int16_t COLLISION_GROUP_MY_AVATAR = 1 << 5; +const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; +const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; +const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; +// ... +const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 15; + + +/* Note: In order for objectA to collide with objectB at the filter stage + * both (groupA & maskB) and (groupB & maskA) must be non-zero. + */ +// DEFAULT collides with everything except COLLISIONLESS +const int16_t COLLISION_MASK_DEFAULT = ~ COLLISION_GROUP_COLLISIONLESS; +const int16_t COLLISION_MASK_STATIC = COLLISION_MASK_DEFAULT; +const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT; +// DEBRIS also doesn't collide with: other DEBRIS, and TRIGGER +const int16_t COLLISION_MASK_DEBRIS = ~ (COLLISION_GROUP_COLLISIONLESS + | COLLISION_GROUP_DEBRIS + | COLLISION_GROUP_TRIGGER); +// TRIGGER also doesn't collide with: DEBRIS, TRIGGER, and STATIC (TRIGGER only detects moveable things that matter) +const int16_t COLLISION_MASK_TRIGGER = COLLISION_MASK_DEBRIS & ~(COLLISION_GROUP_STATIC); +// AVATAR also doesn't collide with: corresponding ATTACHMENT +const int16_t COLLISION_MASK_MY_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_ATTACHMENT); +const int16_t COLLISION_MASK_MY_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_AVATAR); +const int16_t COLLISION_MASK_OTHER_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_ATTACHMENT); +const int16_t COLLISION_MASK_OTHER_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_AVATAR); +// ... +const int16_t COLLISION_MASK_COLLISIONLESS = 0; + const float HALF_SIMULATION_EXTENT = 512.0f; // meters // simple class for keeping track of contacts @@ -91,9 +146,12 @@ public: void dumpNextStats() { _dumpNextStats = true; } + // TODO: Andrew to move these to ObjectMotionState static bool physicsInfoIsActive(void* physicsInfo); static bool getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn); + int16_t getCollisionMask(int16_t group) const; + private: void removeContacts(ObjectMotionState* motionState); @@ -121,6 +179,7 @@ private: QUuid _sessionID; CollisionEvents _collisionEvents; + btHashMap _collisionMasks; }; #endif // hifi_PhysicsEngine_h From a989998816b9b62f1d9933f17f86943b4d20f675 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 14:13:30 -0700 Subject: [PATCH 10/43] fix typo in comment --- libraries/shared/src/PhysicsHelpers.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/shared/src/PhysicsHelpers.cpp b/libraries/shared/src/PhysicsHelpers.cpp index be06920325..578c85683b 100644 --- a/libraries/shared/src/PhysicsHelpers.cpp +++ b/libraries/shared/src/PhysicsHelpers.cpp @@ -5,7 +5,7 @@ // Created by Andrew Meadows 2015.01.27 // Unless otherwise copyrighted: Copyright 2015 High Fidelity, Inc. // -// Unless otherwise licensced: Distributed under the Apache License, Version 2.0. +// Unless otherwise licensed: Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // From ec0b4a956aad62f12f0c4051ebffe6c6a640ca6f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 14:13:51 -0700 Subject: [PATCH 11/43] move collision group consts to shared lib --- interface/src/avatar/AvatarMotionState.cpp | 2 +- .../src/DynamicCharacterController.cpp | 3 +- libraries/physics/src/EntityMotionState.cpp | 1 + libraries/physics/src/PhysicsEngine.cpp | 2 + libraries/physics/src/PhysicsEngine.h | 55 ------------- libraries/shared/src/PhysicsCollisionGroups.h | 79 +++++++++++++++++++ 6 files changed, 85 insertions(+), 57 deletions(-) create mode 100644 libraries/shared/src/PhysicsCollisionGroups.h diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index 7a5fb5662c..06da384a94 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -10,7 +10,7 @@ // #include -#include +#include #include "Avatar.h" #include "AvatarMotionState.h" diff --git a/libraries/physics/src/DynamicCharacterController.cpp b/libraries/physics/src/DynamicCharacterController.cpp index b55975c11a..1fca236f63 100644 --- a/libraries/physics/src/DynamicCharacterController.cpp +++ b/libraries/physics/src/DynamicCharacterController.cpp @@ -3,9 +3,10 @@ #include #include +#include + #include "BulletUtil.h" #include "DynamicCharacterController.h" -#include "PhysicsEngine.h" const btVector3 LOCAL_UP_AXIS(0.0f, 1.0f, 0.0f); const float DEFAULT_GRAVITY = -5.0f; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index c7cbca7ea7..9bac73c945 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -11,6 +11,7 @@ #include #include +#include #include "BulletUtil.h" #include "EntityMotionState.h" diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 5d6823c403..c27eaafdfd 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include "ObjectMotionState.h" #include "PhysicsEngine.h" #include "PhysicsHelpers.h" diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index f0bd8ba4e9..edc6615a26 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -25,61 +25,6 @@ #include "ObjectMotionState.h" #include "ThreadSafeDynamicsWorld.h" -/* Note: These are the collision groups defined in btBroadphaseProxy. Only - * DefaultFilter and StaticFilter are explicitly used by Bullet (when the - * collision filter of an object is not manually specified), the rest are - * merely suggestions. - * -enum CollisionFilterGroups { - DefaultFilter = 1, - StaticFilter = 2, - KinematicFilter = 4, - DebrisFilter = 8, - SensorTrigger = 16, - CharacterFilter = 32, - AllFilter = -1 -} - * - * When using custom collision filters we pretty much need to do all or nothing. - * We'll be doing it all which means we define our own groups and build custom masks - * for everything. - * -*/ - -const int16_t COLLISION_GROUP_DEFAULT = 1 << 0; -const int16_t COLLISION_GROUP_STATIC = 1 << 1; -const int16_t COLLISION_GROUP_KINEMATIC = 1 << 2; -const int16_t COLLISION_GROUP_DEBRIS = 1 << 3; -const int16_t COLLISION_GROUP_TRIGGER = 1 << 4; -const int16_t COLLISION_GROUP_MY_AVATAR = 1 << 5; -const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; -const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; -const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; -// ... -const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 15; - - -/* Note: In order for objectA to collide with objectB at the filter stage - * both (groupA & maskB) and (groupB & maskA) must be non-zero. - */ -// DEFAULT collides with everything except COLLISIONLESS -const int16_t COLLISION_MASK_DEFAULT = ~ COLLISION_GROUP_COLLISIONLESS; -const int16_t COLLISION_MASK_STATIC = COLLISION_MASK_DEFAULT; -const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT; -// DEBRIS also doesn't collide with: other DEBRIS, and TRIGGER -const int16_t COLLISION_MASK_DEBRIS = ~ (COLLISION_GROUP_COLLISIONLESS - | COLLISION_GROUP_DEBRIS - | COLLISION_GROUP_TRIGGER); -// TRIGGER also doesn't collide with: DEBRIS, TRIGGER, and STATIC (TRIGGER only detects moveable things that matter) -const int16_t COLLISION_MASK_TRIGGER = COLLISION_MASK_DEBRIS & ~(COLLISION_GROUP_STATIC); -// AVATAR also doesn't collide with: corresponding ATTACHMENT -const int16_t COLLISION_MASK_MY_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_ATTACHMENT); -const int16_t COLLISION_MASK_MY_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_AVATAR); -const int16_t COLLISION_MASK_OTHER_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_ATTACHMENT); -const int16_t COLLISION_MASK_OTHER_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_AVATAR); -// ... -const int16_t COLLISION_MASK_COLLISIONLESS = 0; - const float HALF_SIMULATION_EXTENT = 512.0f; // meters // simple class for keeping track of contacts diff --git a/libraries/shared/src/PhysicsCollisionGroups.h b/libraries/shared/src/PhysicsCollisionGroups.h new file mode 100644 index 0000000000..cce9637cd4 --- /dev/null +++ b/libraries/shared/src/PhysicsCollisionGroups.h @@ -0,0 +1,79 @@ +// +// PhysicsCollisionGroups.h +// libraries/shared/src +// +// Created by Andrew Meadows 2015.06.03 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_PhysicsCollisionGroups_h +#define hifi_PhysicsCollisionGroups_h + +#include + +/* Note: These are the Bullet collision groups defined in btBroadphaseProxy. Only + * DefaultFilter and StaticFilter are explicitly used by Bullet (when the collision + * filter of an object is not manually specified), the rest are merely suggestions. + * +enum CollisionFilterGroups { + DefaultFilter = 1, + StaticFilter = 2, + KinematicFilter = 4, + DebrisFilter = 8, + SensorTrigger = 16, + CharacterFilter = 32, + AllFilter = -1 +} + * + * When using custom collision filters we pretty much need to do all or nothing. + * We'll be doing it all which means we define our own groups and build custom masks + * for everything. + * +*/ + +const int16_t COLLISION_GROUP_DEFAULT = 1 << 0; +const int16_t COLLISION_GROUP_STATIC = 1 << 1; +const int16_t COLLISION_GROUP_KINEMATIC = 1 << 2; +const int16_t COLLISION_GROUP_DEBRIS = 1 << 3; +const int16_t COLLISION_GROUP_TRIGGER = 1 << 4; +const int16_t COLLISION_GROUP_MY_AVATAR = 1 << 5; +const int16_t COLLISION_GROUP_OTHER_AVATAR = 1 << 6; +const int16_t COLLISION_GROUP_MY_ATTACHMENT = 1 << 7; +const int16_t COLLISION_GROUP_OTHER_ATTACHMENT = 1 << 8; +// ... +const int16_t COLLISION_GROUP_COLLISIONLESS = 1 << 15; + + +/* Note: In order for objectA to collide with objectB at the filter stage + * both (groupA & maskB) and (groupB & maskA) must be non-zero. + */ + +// DEFAULT collides with everything except COLLISIONLESS +const int16_t COLLISION_MASK_DEFAULT = ~ COLLISION_GROUP_COLLISIONLESS; + +// STATIC also doesn't collide with other STATIC +const int16_t COLLISION_MASK_STATIC = ~ (COLLISION_GROUP_COLLISIONLESS | COLLISION_MASK_STATIC); + +const int16_t COLLISION_MASK_KINEMATIC = COLLISION_MASK_DEFAULT; + +// DEBRIS also doesn't collide with other DEBRIS, or TRIGGER +const int16_t COLLISION_MASK_DEBRIS = ~ (COLLISION_GROUP_COLLISIONLESS + | COLLISION_GROUP_DEBRIS + | COLLISION_GROUP_TRIGGER); + +// TRIGGER also doesn't collide with DEBRIS, TRIGGER, or STATIC (TRIGGER only detects moveable things that matter) +const int16_t COLLISION_MASK_TRIGGER = COLLISION_MASK_DEBRIS & ~(COLLISION_GROUP_STATIC); + +// AVATAR also doesn't collide with corresponding ATTACHMENTs +const int16_t COLLISION_MASK_MY_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_ATTACHMENT); +const int16_t COLLISION_MASK_MY_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_MY_AVATAR); +const int16_t COLLISION_MASK_OTHER_AVATAR = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_ATTACHMENT); +const int16_t COLLISION_MASK_OTHER_ATTACHMENT = ~(COLLISION_GROUP_COLLISIONLESS | COLLISION_GROUP_OTHER_AVATAR); + +// COLLISIONLESS gets an empty mask. +const int16_t COLLISION_MASK_COLLISIONLESS = 0; + +#endif // hifi_PhysicsCollisionGroups_h From 8e61a10bcf365c24924a635c8ad2c48d8f4ca30f Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 14:22:48 -0700 Subject: [PATCH 12/43] compute collision group for entity --- libraries/physics/src/EntityMotionState.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 9bac73c945..f2c86edd1f 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -521,5 +521,13 @@ QString EntityMotionState::getName() { // virtual int16_t EntityMotionState::computeCollisionGroup() { + switch (computeObjectMotionType()){ + case MOTION_TYPE_STATIC: + return COLLISION_GROUP_STATIC; + case MOTION_TYPE_KINEMATIC: + return COLLISION_GROUP_KINEMATIC; + default: + break; + } return COLLISION_GROUP_DEFAULT; } From b0ca2df3aa52e4b73242bd8ba173a13c49f910d8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Wed, 3 Jun 2015 14:56:04 -0700 Subject: [PATCH 13/43] move API from PhysicsEngine to ObjectMotionState --- .../src/RenderableDebugableEntityItem.cpp | 3 +- libraries/physics/src/ObjectMotionState.cpp | 1 + libraries/physics/src/ObjectMotionState.h | 2 ++ libraries/physics/src/PhysicsEngine.cpp | 34 ------------------- libraries/physics/src/PhysicsEngine.h | 4 --- 5 files changed, 5 insertions(+), 39 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp b/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp index 017cb289f0..7854aee82f 100644 --- a/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableDebugableEntityItem.cpp @@ -80,7 +80,8 @@ void RenderableDebugableEntityItem::render(EntityItem* entity, RenderArgs* args) renderBoundingBox(entity, args, 0.3f, yellowColor); } - if (PhysicsEngine::physicsInfoIsActive(entity->getPhysicsInfo())) { + ObjectMotionState* motionState = static_cast(entity->getPhysicsInfo()); + if (motionState && motionState->isActive()) { renderHoverDot(entity, args); } } diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 57b75f0f3b..e2f248ead7 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -200,3 +200,4 @@ void ObjectMotionState::updateBodyMassProperties() { _body->setMassProps(mass, inertia); _body->updateInertiaTensor(); } + diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index fc0c58b5da..4a9fd769c8 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -125,6 +125,8 @@ public: virtual int16_t computeCollisionGroup() = 0; + bool isActive() const { return _body ? _body->isActive() : false; } + friend class PhysicsEngine; protected: diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index c27eaafdfd..b6a509a874 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -431,40 +431,6 @@ void PhysicsEngine::setCharacterController(DynamicCharacterController* character } } -// static -bool PhysicsEngine::physicsInfoIsActive(void* physicsInfo) { - if (!physicsInfo) { - return false; - } - - ObjectMotionState* motionState = static_cast(physicsInfo); - btRigidBody* body = motionState->getRigidBody(); - if (!body) { - return false; - } - - return body->isActive(); -} - -// static -bool PhysicsEngine::getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn) { - if (!physicsInfo) { - return false; - } - - ObjectMotionState* motionState = static_cast(physicsInfo); - btRigidBody* body = motionState->getRigidBody(); - if (!body) { - return false; - } - - const btTransform& worldTrans = body->getCenterOfMassTransform(); - positionReturn = bulletToGLM(worldTrans.getOrigin()) + ObjectMotionState::getWorldOffset(); - rotationReturn = bulletToGLM(worldTrans.getRotation()); - - return true; -} - int16_t PhysicsEngine::getCollisionMask(int16_t group) const { const int16_t* mask = _collisionMasks.find(btHashInt((int)group)); return mask ? *mask : COLLISION_MASK_DEFAULT; diff --git a/libraries/physics/src/PhysicsEngine.h b/libraries/physics/src/PhysicsEngine.h index edc6615a26..db00a2ba01 100644 --- a/libraries/physics/src/PhysicsEngine.h +++ b/libraries/physics/src/PhysicsEngine.h @@ -91,10 +91,6 @@ public: void dumpNextStats() { _dumpNextStats = true; } - // TODO: Andrew to move these to ObjectMotionState - static bool physicsInfoIsActive(void* physicsInfo); - static bool getBodyLocation(void* physicsInfo, glm::vec3& positionReturn, glm::quat& rotationReturn); - int16_t getCollisionMask(int16_t group) const; private: From 7f0a7b4f7ededc30b4f583ad9b4b61cab9e8a437 Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Wed, 3 Jun 2015 17:15:50 -0700 Subject: [PATCH 14/43] Fixing web entity glow and 'back' behavior --- .../src/RenderableWebEntityItem.cpp | 32 ++++++++++++++++--- .../src/RenderableWebEntityItem.h | 1 + 2 files changed, 29 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 2e623de6c5..74405ba586 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -8,10 +8,13 @@ #include "RenderableWebEntityItem.h" +#include + #include #include +#include #include #include #include @@ -64,7 +67,6 @@ RenderableWebEntityItem::~RenderableWebEntityItem() { void RenderableWebEntityItem::render(RenderArgs* args) { QOpenGLContext * currentContext = QOpenGLContext::currentContext(); QSurface * currentSurface = currentContext->surface(); - if (!_webSurface) { _webSurface = new OffscreenQmlSurface(); _webSurface->create(currentContext); @@ -98,16 +100,35 @@ void RenderableWebEntityItem::render(RenderArgs* args) { return; } + if (event->button() == Qt::MouseButton::RightButton) { + if (event->type() == QEvent::MouseButtonPress) { + const QMouseEvent* mouseEvent = static_cast(event); + _lastPress = toGlm(mouseEvent->pos()); + } + } + if (intersection.entityID == getID()) { if (event->button() == Qt::MouseButton::RightButton) { if (event->type() == QEvent::MouseButtonRelease) { - AbstractViewStateInterface::instance()->postLambdaEvent([this] { - QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); - }); + const QMouseEvent* mouseEvent = static_cast(event); + ivec2 dist = glm::abs(toGlm(mouseEvent->pos()) - _lastPress); + if (!glm::any(glm::greaterThan(dist, ivec2(1)))) { + AbstractViewStateInterface::instance()->postLambdaEvent([this] { + QMetaObject::invokeMethod(_webSurface->getRootItem(), "goBack"); + }); + } + _lastPress = ivec2(INT_MIN); } return; } + // FIXME doesn't work... double click events not received + if (event->type() == QEvent::MouseButtonDblClick) { + AbstractViewStateInterface::instance()->postLambdaEvent([this] { + _webSurface->getRootItem()->setProperty("url", _sourceUrl); + }); + } + if (event->button() == Qt::MouseButton::MiddleButton) { if (event->type() == QEvent::MouseButtonRelease) { AbstractViewStateInterface::instance()->postLambdaEvent([this] { @@ -133,6 +154,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { QCoreApplication::sendEvent(_webSurface->getWindow(), &mappedEvent); } }; + EntityTreeRenderer* renderer = static_cast(args->_renderer); QObject::connect(renderer, &EntityTreeRenderer::mousePressOnEntity, forwardMouseEvent); QObject::connect(renderer, &EntityTreeRenderer::mouseReleaseOnEntity, forwardMouseEvent); @@ -147,6 +169,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { _webSurface->resize(QSize(dims.x, dims.y)); currentContext->makeCurrent(currentSurface); + Glower glow(0); PerformanceTimer perfTimer("RenderableWebEntityItem::render"); assert(getType() == EntityTypes::Web); glm::vec3 position = getPosition(); @@ -181,6 +204,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { } void RenderableWebEntityItem::setSourceUrl(const QString& value) { + qDebug() << "Setting web entity source URL to " << value; if (_sourceUrl != value) { _sourceUrl = value; if (_webSurface) { diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.h b/libraries/entities-renderer/src/RenderableWebEntityItem.h index 8dad2a0855..559392367c 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.h +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.h @@ -29,6 +29,7 @@ private: OffscreenQmlSurface* _webSurface{ nullptr }; QMetaObject::Connection _connection; uint32_t _texture{ 0 }; + ivec2 _lastPress{ INT_MIN }; QMutex _textureLock; }; From a4340b17e964e45ea4cbc9c4b0b59f00d797d07d Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Jun 2015 14:47:04 +0200 Subject: [PATCH 15/43] Remove deprecated render stats --- interface/src/ui/Stats.cpp | 21 ++------- .../src/EntityTreeRenderer.cpp | 6 --- libraries/render-utils/src/Model.cpp | 46 ++++--------------- libraries/render/src/render/DrawTask.cpp | 9 ---- libraries/shared/src/RenderArgs.h | 11 ----- 5 files changed, 12 insertions(+), 81 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 5f3b67ab53..069a8d6fd2 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -467,28 +467,13 @@ void Stats::display( horizontalOffset += 5; // Model/Entity render details - EntityTreeRenderer* entities = Application::getInstance()->getEntities(); octreeStats.str(""); - octreeStats << "Entity Items rendered: " << _renderDetails._itemsRendered - << " / Out of view:" << _renderDetails._itemsOutOfView - << " / Too small:" << _renderDetails._itemsTooSmall; + octreeStats << "Triangles: " << _renderDetails._trianglesRendered + << " / Quads:" << _renderDetails._quadsRendered + << " / Material Switches:" << _renderDetails._materialSwitches; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); if (_expanded) { - octreeStats.str(""); - octreeStats << " Meshes rendered: " << _renderDetails._meshesRendered - << " / Out of view:" << _renderDetails._meshesOutOfView - << " / Too small:" << _renderDetails._meshesTooSmall; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - - octreeStats.str(""); - octreeStats << " Triangles: " << _renderDetails._trianglesRendered - << " / Quads:" << _renderDetails._quadsRendered - << " / Material Switches:" << _renderDetails._materialSwitches; - verticalOffset += STATS_PELS_PER_LINE; - drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); - octreeStats.str(""); octreeStats << " Mesh Parts Rendered Opaque: " << _renderDetails._opaqueMeshPartsRendered << " / Translucent:" << _renderDetails._translucentMeshPartsRendered; diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 02a3747cec..6446194452 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -654,7 +654,6 @@ void EntityTreeRenderer::renderProxies(EntityItemPointer entity, RenderArgs* arg } void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) { - args->_outsideEngineDetails._elementsTouched++; // actually render it here... // we need to iterate the actual entityItems of the element EntityTreeElement* entityTreeElement = static_cast(element); @@ -719,15 +718,10 @@ void EntityTreeRenderer::renderElement(OctreeElement* element, RenderArgs* args) glower = new Glower(args, entityItem->getGlowLevel()); } entityItem->render(args); - args->_outsideEngineDetails._itemsRendered++; if (glower) { delete glower; } - } else { - args->_outsideEngineDetails._itemsTooSmall++; } - } else { - args->_outsideEngineDetails._itemsOutOfView++; } } } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6f4b9bca9e..9c21c1a21a 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1118,11 +1118,6 @@ bool Model::renderCore(RenderArgs* args, float alpha) { // restore all the default material settings _viewState->setupWorldLight(); - if (args) { - args->_outsideEngineDetails._translucentMeshPartsRendered = translucentMeshPartsRendered; - args->_outsideEngineDetails._opaqueMeshPartsRendered = opaqueMeshPartsRendered; - } - #ifdef WANT_DEBUG_MESHBOXES renderDebugMeshBoxes(); #endif @@ -2189,11 +2184,6 @@ void Model::endScene(RenderArgs* args) { // Back to no program GLBATCH(glUseProgram)(0); - if (args) { - args->_outsideEngineDetails._translucentMeshPartsRendered = translucentParts; - args->_outsideEngineDetails._opaqueMeshPartsRendered = opaqueMeshPartsRendered; - } - } // Render! @@ -2307,8 +2297,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran pickPrograms(batch, mode, translucent, alphaThreshold, hasLightmap, hasTangents, hasSpecular, isSkinned, wireframe, args, locations); - - int meshPartsRendered = 0; updateVisibleJointStates(); // if our index is ever out of range for either meshes or networkMeshes, then skip it, and set our _meshGroupsKnown @@ -2438,16 +2426,14 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran float emissiveOffset = part.emissiveParams.x; float emissiveScale = part.emissiveParams.y; GLBATCH(glUniform2f)(locations->emissiveParams, emissiveOffset, emissiveScale); - + Texture* emissiveMap = networkPart.emissiveTexture.data(); batch.setUniformTexture(locations->emissiveTextureUnit, !emissiveMap ? - textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); + textureCache->getWhiteTexture() : emissiveMap->getGPUTexture()); } } } - meshPartsRendered++; - if (part.quadIndices.size() > 0) { batch.drawIndexed(gpu::QUADS, part.quadIndices.size(), offset); offset += part.quadIndices.size() * sizeof(int); @@ -2463,6 +2449,12 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran const int INDICES_PER_QUAD = 4; args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; + + if (translucent) { + args->_details._translucentMeshPartsRendered++; + } else { + args->_details._opaqueMeshPartsRendered++; + } } } @@ -2681,8 +2673,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod // if we got here, then check to see if this mesh is in view if (args) { bool shouldRender = true; - args->_outsideEngineDetails._meshesConsidered++; - if (args->_viewFrustum) { shouldRender = forceRenderMeshes || @@ -2692,17 +2682,10 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod float distance = args->_viewFrustum->distanceToCamera(_calculatedMeshBoxes.at(i).calcCenter()); shouldRender = !_viewState ? false : _viewState->shouldRenderMesh(_calculatedMeshBoxes.at(i).getLargestDimension(), distance); - if (!shouldRender) { - args->_outsideEngineDetails._meshesTooSmall++; - } - } else { - args->_outsideEngineDetails._meshesOutOfView++; } } - if (shouldRender) { - args->_outsideEngineDetails._meshesRendered++; - } else { + if (!shouldRender) { continue; // skip this mesh } } @@ -2793,11 +2776,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod batch.setUniformTexture(locations->specularTextureUnit, !specularMap ? textureCache->getWhiteTexture() : specularMap->getGPUTexture()); } - - if (args) { - args->_outsideEngineDetails._materialSwitches++; - } - } // HACK: For unkwon reason (yet!) this code that should be assigned only if the material changes need to be called for every @@ -2828,12 +2806,6 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod offset += part.triangleIndices.size() * sizeof(int); } - if (args) { - const int INDICES_PER_TRIANGLE = 3; - const int INDICES_PER_QUAD = 4; - args->_outsideEngineDetails._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; - args->_outsideEngineDetails._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; - } } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 55e489d5ae..f396fb45ab 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -63,8 +63,6 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; - - int startingSize = outItems.size(); // Culling / LOD for (auto id : inItems) { @@ -81,18 +79,11 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont bool outOfView = args->_viewFrustum->boxInFrustum(bound) == ViewFrustum::OUTSIDE; if (!outOfView) { bool bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true; - if (bigEnoughToRender) { outItems.push_back(id); // One more Item to render - } else { - args->_details._itemsTooSmall++; } - } else { - args->_details._itemsOutOfView++; } } - - args->_details._itemsRendered += (outItems.size() - startingSize); } struct ItemBound { diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index 1bce99907c..b2a0d75cd6 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -23,16 +23,6 @@ class Context; } struct RenderDetails { - int _elementsTouched = 0; - int _itemsRendered = 0; - int _itemsOutOfView = 0; - int _itemsTooSmall = 0; - - int _meshesConsidered = 0; - int _meshesRendered = 0; - int _meshesOutOfView = 0; - int _meshesTooSmall = 0; - int _materialSwitches = 0; int _trianglesRendered = 0; int _quadsRendered = 0; @@ -89,7 +79,6 @@ public: ShoudRenderFunctor _shouldRender; RenderDetails _details; - RenderDetails _outsideEngineDetails; float _alphaThreshold = 0.5f; }; From 93b44e6846c242fe3f06922d90b3a526c7b1480f Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Thu, 4 Jun 2015 18:46:47 +0200 Subject: [PATCH 16/43] Collect stats on translucent/opaque mesh parts --- interface/src/ui/Stats.cpp | 18 ++++++++++-- libraries/render-utils/src/Model.cpp | 6 ---- libraries/render/src/render/DrawTask.cpp | 14 +++++++++ libraries/shared/src/RenderArgs.h | 37 ++++++++++++++++++++++-- 4 files changed, 64 insertions(+), 11 deletions(-) diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 069a8d6fd2..32df75c46d 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -475,8 +475,22 @@ void Stats::display( if (_expanded) { octreeStats.str(""); - octreeStats << " Mesh Parts Rendered Opaque: " << _renderDetails._opaqueMeshPartsRendered - << " / Translucent:" << _renderDetails._translucentMeshPartsRendered; + octreeStats << " Mesh Parts Rendered Opaque: " << _renderDetails._opaque._rendered + << " / Translucent:" << _renderDetails._translucent._rendered; + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); + + octreeStats.str(""); + octreeStats << " Opaque considered: " << _renderDetails._opaque._considered + << " / Out of view:" << _renderDetails._opaque._outOfView + << " / Too small:" << _renderDetails._opaque._tooSmall; + verticalOffset += STATS_PELS_PER_LINE; + drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); + + octreeStats.str(""); + octreeStats << " Translucent considered: " << _renderDetails._translucent._considered + << " / Out of view:" << _renderDetails._translucent._outOfView + << " / Too small:" << _renderDetails._translucent._tooSmall; verticalOffset += STATS_PELS_PER_LINE; drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)octreeStats.str().c_str(), color); } diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index ae9991a3e4..fdb398c830 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -2216,12 +2216,6 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran const int INDICES_PER_QUAD = 4; args->_details._trianglesRendered += part.triangleIndices.size() / INDICES_PER_TRIANGLE; args->_details._quadsRendered += part.quadIndices.size() / INDICES_PER_QUAD; - - if (translucent) { - args->_details._translucentMeshPartsRendered++; - } else { - args->_details._opaqueMeshPartsRendered++; - } } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index f396fb45ab..8011b3a715 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -63,7 +63,10 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont auto& scene = sceneContext->_scene; RenderArgs* args = renderContext->args; + auto renderDetails = renderContext->args->_details._item; + renderDetails->_considered += inItems.size(); + // Culling / LOD for (auto id : inItems) { auto item = scene->getItem(id); @@ -81,9 +84,14 @@ void render::cullItems(const SceneContextPointer& sceneContext, const RenderCont bool bigEnoughToRender = (args->_shouldRender) ? args->_shouldRender(args, bound) : true; if (bigEnoughToRender) { outItems.push_back(id); // One more Item to render + } else { + renderDetails->_tooSmall++; } + } else { + renderDetails->_outOfView++; } } + renderDetails->_rendered += outItems.size(); } struct ItemBound { @@ -220,6 +228,7 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer // render opaques auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(ItemFilter::Builder::opaqueShape()); + auto& renderDetails = renderContext->args->_details; ItemIDs inItems; inItems.reserve(items.size()); @@ -232,7 +241,9 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer ItemIDs culledItems; if (renderContext->_cullOpaque) { + renderDetails.pointTo(RenderDetails::OPAQUE); cullItems(sceneContext, renderContext, renderedItems, culledItems); + renderDetails.pointTo(RenderDetails::OTHER); renderedItems = culledItems; } @@ -283,6 +294,7 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo // render transparents auto& scene = sceneContext->_scene; auto& items = scene->getMasterBucket().at(ItemFilter::Builder::transparentShape()); + auto& renderDetails = renderContext->args->_details; ItemIDs inItems; inItems.reserve(items.size()); @@ -295,7 +307,9 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo ItemIDs culledItems; if (renderContext->_cullTransparent) { + renderDetails.pointTo(RenderDetails::TRANSLUCENT); cullItems(sceneContext, renderContext, inItems, culledItems); + renderDetails.pointTo(RenderDetails::OTHER); renderedItems = culledItems; } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index b2a0d75cd6..cdfdfb9c5f 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -22,13 +22,44 @@ class Batch; class Context; } -struct RenderDetails { +class RenderDetails { +public: + enum Type { + OPAQUE, + TRANSLUCENT, + OTHER + }; + + struct Items { + int _considered = 0; + int _rendered = 0; + int _outOfView = 0; + int _tooSmall = 0; + }; + int _materialSwitches = 0; int _trianglesRendered = 0; int _quadsRendered = 0; - int _translucentMeshPartsRendered = 0; - int _opaqueMeshPartsRendered = 0; + Items _opaque; + Items _translucent; + Items _other; + + Items* _item = &_other; + + void pointTo(Type type) { + switch (type) { + case OPAQUE: + _item = &_opaque; + break; + case TRANSLUCENT: + _item = &_translucent; + break; + case OTHER: + _item = &_other; + break; + } + } }; class RenderArgs { From 6ea4c5831903adf3b965651eabc584e107500a1b Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 10:22:01 -0700 Subject: [PATCH 17/43] material changes are an "easy" property to update --- libraries/physics/src/ObjectMotionState.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index 246ed16627..b0a06ef9e0 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -39,11 +39,12 @@ enum MotionStateType { // and re-added to the physics engine and "easy" which just updates the body properties. const uint32_t HARD_DIRTY_PHYSICS_FLAGS = (uint32_t)(EntityItem::DIRTY_MOTION_TYPE | EntityItem::DIRTY_SHAPE); const uint32_t EASY_DIRTY_PHYSICS_FLAGS = (uint32_t)(EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES | - EntityItem::DIRTY_MASS | EntityItem::DIRTY_COLLISION_GROUP); + EntityItem::DIRTY_MASS | EntityItem::DIRTY_COLLISION_GROUP | + EntityItem::DIRTY_MATERIAL); // These are the set of incoming flags that the PhysicsEngine needs to hear about: -const uint32_t DIRTY_PHYSICS_FLAGS = HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS | - EntityItem::DIRTY_MATERIAL | (uint32_t)EntityItem::DIRTY_PHYSICS_ACTIVATION; +const uint32_t DIRTY_PHYSICS_FLAGS = (uint32_t)(HARD_DIRTY_PHYSICS_FLAGS | EASY_DIRTY_PHYSICS_FLAGS | + EntityItem::DIRTY_PHYSICS_ACTIVATION); // These are the outgoing flags that the PhysicsEngine can affect: const uint32_t OUTGOING_DIRTY_PHYSICS_FLAGS = EntityItem::DIRTY_TRANSFORM | EntityItem::DIRTY_VELOCITIES; From 0514736a3efab66bf8d0a58d9f2bc6c9f0f67d0a Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 11:24:10 -0700 Subject: [PATCH 18/43] remove last of *InDomainUnits code --- libraries/entities/src/EntityItem.cpp | 51 ++++----------------------- libraries/entities/src/EntityItem.h | 5 --- 2 files changed, 7 insertions(+), 49 deletions(-) diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 5d09f4aa4a..aa10a2e52e 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -82,7 +82,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert } EntityItem::~EntityItem() { - // these pointers MUST be NULL at delete, else we probably have a dangling backpointer + // these pointers MUST be correct at delete, else we probably have a dangling backpointer // to this EntityItem in the corresponding data structure. assert(!_simulated); assert(!_element); @@ -517,12 +517,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef EntityPropertyFlags propertyFlags = encodedPropertyFlags; dataAt += propertyFlags.getEncodedLength(); bytesRead += propertyFlags.getEncodedLength(); - bool useMeters = (args.bitstreamVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS); - if (useMeters) { - READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition); - } else { - READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePositionInDomainUnits); - } + READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, updatePosition); // Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) { @@ -536,22 +531,13 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef } } } else { - if (useMeters) { - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions); - } else { - READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensionsInDomainUnits); - } + READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, updateDimensions); } READ_ENTITY_PROPERTY(PROP_ROTATION, glm::quat, updateRotation); READ_ENTITY_PROPERTY(PROP_DENSITY, float, updateDensity); - if (useMeters) { - READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity); - READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity); - } else { - READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocityInDomainUnits); - READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravityInDomainUnits); - } + READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, updateVelocity); + READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, updateGravity); if (args.bitstreamVersion >= VERSION_ENTITIES_HAVE_ACCELERATION) { READ_ENTITY_PROPERTY(PROP_ACCELERATION, glm::vec3, setAcceleration); } @@ -562,11 +548,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LIFETIME, float, updateLifetime); READ_ENTITY_PROPERTY(PROP_SCRIPT, QString, setScript); READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, setRegistrationPoint); - if (useMeters) { - READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); - } else { - READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees); - } + READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity); + //READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocityInDegrees); READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, updateAngularDamping); READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions); @@ -1127,11 +1110,6 @@ void EntityItem::computeShapeInfo(ShapeInfo& info) { info.setParams(getShapeType(), 0.5f * getDimensions()); } -void EntityItem::updatePositionInDomainUnits(const glm::vec3& value) { - glm::vec3 position = value * (float)TREE_SCALE; - updatePosition(position); -} - void EntityItem::updatePosition(const glm::vec3& value) { auto delta = glm::distance(_position, value); if (delta > IGNORE_POSITION_DELTA) { @@ -1143,11 +1121,6 @@ void EntityItem::updatePosition(const glm::vec3& value) { } } -void EntityItem::updateDimensionsInDomainUnits(const glm::vec3& value) { - glm::vec3 dimensions = value * (float)TREE_SCALE; - updateDimensions(dimensions); -} - void EntityItem::updateDimensions(const glm::vec3& value) { auto delta = glm::distance(_dimensions, value); if (delta > IGNORE_DIMENSIONS_DELTA) { @@ -1199,11 +1172,6 @@ void EntityItem::updateMass(float mass) { } } -void EntityItem::updateVelocityInDomainUnits(const glm::vec3& value) { - glm::vec3 velocity = value * (float)TREE_SCALE; - updateVelocity(velocity); -} - void EntityItem::updateVelocity(const glm::vec3& value) { auto delta = glm::distance(_velocity, value); if (delta > IGNORE_LINEAR_VELOCITY_DELTA) { @@ -1229,11 +1197,6 @@ void EntityItem::updateDamping(float value) { } } -void EntityItem::updateGravityInDomainUnits(const glm::vec3& value) { - glm::vec3 gravity = value * (float) TREE_SCALE; - updateGravity(gravity); -} - void EntityItem::updateGravity(const glm::vec3& value) { auto delta = glm::distance(_gravity, value); if (delta > IGNORE_GRAVITY_DELTA) { diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 5f37510b67..75fe7be99c 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -308,22 +308,17 @@ public: virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } // updateFoo() methods to be used when changes need to be accumulated in the _dirtyFlags - void updatePositionInDomainUnits(const glm::vec3& value); void updatePosition(const glm::vec3& value); - void updateDimensionsInDomainUnits(const glm::vec3& value); void updateDimensions(const glm::vec3& value); void updateRotation(const glm::quat& rotation); void updateDensity(float value); void updateMass(float value); - void updateVelocityInDomainUnits(const glm::vec3& value); void updateVelocity(const glm::vec3& value); void updateDamping(float value); void updateRestitution(float value); void updateFriction(float value); - void updateGravityInDomainUnits(const glm::vec3& value); void updateGravity(const glm::vec3& value); void updateAngularVelocity(const glm::vec3& value); - void updateAngularVelocityInDegrees(const glm::vec3& value) { updateAngularVelocity(glm::radians(value)); } void updateAngularDamping(float value); void updateIgnoreForCollisions(bool value); void updateCollisionsWillMove(bool value); From aff751b4e655106b03689dbaa3c95d712b3883e8 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 11:26:35 -0700 Subject: [PATCH 19/43] remove old debug assert --- libraries/entities/src/EntityTree.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.cpp b/libraries/entities/src/EntityTree.cpp index 937472820e..47eb845daa 100644 --- a/libraries/entities/src/EntityTree.cpp +++ b/libraries/entities/src/EntityTree.cpp @@ -681,7 +681,6 @@ void EntityTree::update() { QSet idsToDelete; for (auto entity : pendingDeletes) { - assert(!entity->getPhysicsInfo()); // TODO: Andrew to remove this after testing idsToDelete.insert(entity->getEntityItemID()); } From 6b03e671d8735018e457b02622fcb61d6b9b23e9 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 11:28:07 -0700 Subject: [PATCH 20/43] remove comment cruft --- libraries/physics/src/PhysicsEngine.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index b622a37136..1f0a4edfb8 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -31,7 +31,6 @@ PhysicsEngine::~PhysicsEngine() { if (_characterController) { _characterController->setDynamicsWorld(nullptr); } - // TODO: delete engine components... if we ever plan to create more than one instance delete _collisionConfig; delete _collisionDispatcher; delete _broadphaseFilter; From 5727400b9af023e8fbcea3a19e0740205c991de2 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 4 Jun 2015 14:20:19 -0700 Subject: [PATCH 21/43] Sound toys script (in examples/soundToys.js) --- examples/example/soundToys.js | 66 +++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 examples/example/soundToys.js diff --git a/examples/example/soundToys.js b/examples/example/soundToys.js new file mode 100644 index 0000000000..9d8c824b90 --- /dev/null +++ b/examples/example/soundToys.js @@ -0,0 +1,66 @@ +"use strict"; +// Creates some objects that each play a sound when they are hit (or when they hit something else). +// +// Created by Howard Stearns on June 3, 2015 +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html + +var Camera, Vec3, Quat, Entities, Script; // Globals defined by HiFi, var'ed here to keep jslint happy. +var HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; +var SOUND_BUCKET = "http://public.highfidelity.io/sounds/Collisions-hitsandslaps/"; +var MAX_ANGULAR_SPEED = Math.PI; +var N_EACH_OBJECTS = 3; + +var ourToys = []; +function deleteAll() { + ourToys.forEach(Entities.deleteEntity); +} +function makeAll() { + var currentPosition = Vec3.sum(Camera.getPosition(), Vec3.multiply(4, Quat.getFront(Camera.getOrientation()))), + right = Vec3.multiply(0.6, Quat.getRight(Camera.getOrientation())), + currentDimensions, + data = [ + ["models/props/Dice/goldDie.fbx", HIFI_PUBLIC_BUCKET + "sounds/dice/diceCollide.wav"], + ["models/props/Pool/ball_8.fbx", HIFI_PUBLIC_BUCKET + "sounds/Collisions-ballhitsandcatches/billiards/collision1.wav"], + ["eric/models/woodFloor.fbx", SOUND_BUCKET + "67LCollision05.wav"] + ]; + currentPosition = Vec3.sum(currentPosition, Vec3.multiply(-1 * data.length * N_EACH_OBJECTS / 2, right)); + function makeOne(model, sound) { + var thisEntity; + function dropOnce() { // Once gravity is added, it will work if picked up and again dropped. + Entities.editEntity(thisEntity, {gravity: {x: 0, y: -9.8, z: 0}}); + Script.removeEventHandler(thisEntity, 'clickDownOnEntity', dropOnce); + } + thisEntity = Entities.addEntity({ + type: "Model", + modelURL: HIFI_PUBLIC_BUCKET + model, + collisionSoundURL: sound, + collisionsWillMove: true, + shapeType: "box", + restitution: 0.8, + dimensions: currentDimensions, + position: currentPosition, + angularVelocity: { + x: Math.random() * MAX_ANGULAR_SPEED, + y: Math.random() * MAX_ANGULAR_SPEED, + z: Math.random() * MAX_ANGULAR_SPEED + } + }); + ourToys.push(thisEntity); + Script.addEventHandler(thisEntity, 'clickDownOnEntity', dropOnce); + currentDimensions = Vec3.multiply(currentDimensions, 2); + currentPosition = Vec3.sum(currentPosition, right); + } + function makeThree(modelSound) { + var i, model = modelSound[0], sound = modelSound[1]; + currentDimensions = {x: 0.1, y: 0.1, z: 0.1}; + for (i = 0; i < N_EACH_OBJECTS; i++) { + makeOne(model, sound); + } + } + data.forEach(makeThree); +} +makeAll(); +Script.scriptEnding.connect(deleteAll); From 5cbb5dadca469653cf3e7b33ecb80fa779ff678f Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 4 Jun 2015 14:21:12 -0700 Subject: [PATCH 22/43] More perspicacious zero. --- libraries/physics/src/ObjectMotionState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 67dc8f294c..f7fc044c92 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -83,7 +83,7 @@ glm::vec3 ObjectMotionState::getBodyLinearVelocity() const { return bulletToGLM(_body->getLinearVelocity()); } glm::vec3 ObjectMotionState::getObjectLinearVelocityChange() const { - return glm::vec3(); // Subclasses override where meaningful. + return glm::vec3(0.0f); // Subclasses override where meaningful. } glm::vec3 ObjectMotionState::getBodyAngularVelocity() const { From 407d3b6a6eff1461d54dd6ff499b3d5e40bd94a5 Mon Sep 17 00:00:00 2001 From: Howard Stearns Date: Thu, 4 Jun 2015 14:23:51 -0700 Subject: [PATCH 23/43] Pitch is dependent on (largest dimension of) minimum bounding, not max. Adjust sound range of full volume. --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 93e302c81b..7fda8214bb 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1134,12 +1134,14 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT // The collision.penetration is a pretty good indicator of changed velocity AFTER the initial contact, // but that first contact depends on exactly where we hit in the physics step. // We can get a more consistent initial-contact energy reading by using the changed velocity. + // Note that velocityChange is not a good indicator for continuing collisions, because it does not distinguish + // between bounce and sliding along a surface. const float linearVelocity = (collision.type == CONTACT_EVENT_TYPE_START) ? glm::length(collision.velocityChange) : glm::length(collision.penetration) * COLLISION_PENETRATION_TO_VELOCITY; const float energy = mass * linearVelocity * linearVelocity / 2.0f; const glm::vec3 position = collision.contactPoint; - const float COLLISION_ENERGY_AT_FULL_VOLUME = (collision.type == CONTACT_EVENT_TYPE_START) ? 10.0f : 0.5f; + const float COLLISION_ENERGY_AT_FULL_VOLUME = (collision.type == CONTACT_EVENT_TYPE_START) ? 150.0f : 5.0f; const float COLLISION_MINIMUM_VOLUME = 0.005f; const float energyFactorOfFull = fmin(1.0f, energy / COLLISION_ENERGY_AT_FULL_VOLUME); if (energyFactorOfFull < COLLISION_MINIMUM_VOLUME) { @@ -1172,7 +1174,7 @@ void EntityTreeRenderer::playEntityCollisionSound(const QUuid& myNodeID, EntityT soxr_io_spec_t spec = soxr_io_spec(SOXR_INT16_I, SOXR_INT16_I); soxr_quality_spec_t qualitySpec = soxr_quality_spec(SOXR_MQ, 0); const int channelCount = sound->isStereo() ? 2 : 1; - const float factor = log(1.0f + (entity->getMaximumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); + const float factor = log(1.0f + (entity->getMinimumAACube().getLargestDimension() / COLLISION_SIZE_FOR_STANDARD_PITCH)) / log(2); const int standardRate = AudioConstants::SAMPLE_RATE; const int resampledRate = standardRate * factor; const int nInputSamples = samples.size() / sizeof(int16_t); From a2ae51371be4e39cae6620b03d39069989bc642b Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 15:44:39 -0700 Subject: [PATCH 24/43] updated pointer.js script to work with new line entity --- examples/pointer.js | 159 +++++++++----------------------------------- 1 file changed, 30 insertions(+), 129 deletions(-) diff --git a/examples/pointer.js b/examples/pointer.js index 32698209a4..5b293c8478 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -1,30 +1,17 @@ // pointer.js // examples // -// Created by Eric Levin on May 26, 2015 +// Created by Seth Alves on May 15th +// Modified by Eric Levin on June 4 // Copyright 2015 High Fidelity, Inc. // // Provides a pointer with option to draw on surfaces // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// var lineEntityID = null; var lineIsRezzed = false; -var altHeld = false; -var lineCreated = false; -var position, positionOffset, prevPosition; -var nearLinePosition; -var strokes = []; -var STROKE_ADJUST = 0.005; -var DISTANCE_DRAW_THRESHOLD = .02; -var drawDistance = 0; - -var LINE_WIDTH = 20; - -var userCanPoint = false; -var userCanDraw = false; var BUTTON_SIZE = 32; var PADDING = 3; @@ -43,16 +30,7 @@ var buttonOnColor = { HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; var screenSize = Controller.getViewportDimensions(); -var drawButton = Overlays.addOverlay("image", { - x: screenSize.x / 2 - BUTTON_SIZE + PADDING * 2, - y: screenSize.y - (BUTTON_SIZE + PADDING), - width: BUTTON_SIZE, - height: BUTTON_SIZE, - imageURL: HIFI_PUBLIC_BUCKET + "images/pencil.png?v2", - color: buttonOffColor, - alpha: 1 -}); - +var userCanPoint = false; var pointerButton = Overlays.addOverlay("image", { x: screenSize.x / 2 - BUTTON_SIZE * 2 + PADDING, y: screenSize.y - (BUTTON_SIZE + PADDING), @@ -61,14 +39,12 @@ var pointerButton = Overlays.addOverlay("image", { imageURL: HIFI_PUBLIC_BUCKET + "images/laser.png", color: buttonOffColor, alpha: 1 -}) +}); -var center = Vec3.sum(MyAvatar.position, Vec3.multiply(2.0, Quat.getFront(Camera.getOrientation()))); -center.y += 0.5; -function calculateNearLinePosition(targetPosition) { +function nearLinePoint(targetPosition) { var handPosition = MyAvatar.getRightPalmPosition(); var along = Vec3.subtract(targetPosition, handPosition); along = Vec3.normalize(along); @@ -87,39 +63,40 @@ function removeLine() { function createOrUpdateLine(event) { - if (!userCanPoint) { - return; - } var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Entities.findRayIntersection(pickRay, true); // accurate picking var props = Entities.getEntityProperties(intersection.entityID); - if (intersection.intersects) { - startPosition = intersection.intersection; - var subtractVec = Vec3.multiply(Vec3.normalize(pickRay.direction), STROKE_ADJUST); - startPosition = Vec3.subtract(startPosition, subtractVec); - nearLinePosition = calculateNearLinePosition(intersection.intersection); - positionOffset = Vec3.subtract(startPosition, nearLinePosition); + if (intersection.intersects && userCanPoint) { + var points = [nearLinePoint(intersection.intersection), intersection.intersection] if (lineIsRezzed) { Entities.editEntity(lineEntityID, { - position: nearLinePosition, - dimensions: positionOffset, + position: nearLinePoint(intersection.intersection), + linePoints: points, + dimensions: { + x: 1, + y: 1, + z: 1 + }, + lifetime: 15 + props.lifespan // renew lifetime }); - if (userCanDraw) { - draw(); - } } else { lineIsRezzed = true; - prevPosition = startPosition; lineEntityID = Entities.addEntity({ type: "Line", - position: nearLinePosition, - dimensions: positionOffset, + position: nearLinePoint(intersection.intersection), + linePoints: points, + dimensions: { + x: 1, + y: 1, + z: 1 + }, color: { red: 255, green: 255, blue: 255 }, + lifetime: 15 // if someone crashes while pointing, don't leave the line there forever. }); } } else { @@ -127,120 +104,44 @@ function createOrUpdateLine(event) { } } -function draw() { - //We only want to draw line if distance between starting and previous point is large enough - drawDistance = Vec3.distance(startPosition, prevPosition); - if (drawDistance < DISTANCE_DRAW_THRESHOLD) { +function mousePressEvent(event) { + if (!event.isLeftButton) { return; } - var offset = Vec3.subtract(startPosition, prevPosition); - strokes.push(Entities.addEntity({ - type: "Line", - position: prevPosition, - dimensions: offset, - color: { - red: 200, - green: 40, - blue: 200 - }, - lineWidth: LINE_WIDTH - })); - prevPosition = startPosition; -} - -function mousePressEvent(event) { - var clickedOverlay = Overlays.getOverlayAtPoint({ + createOrUpdateLine(event); + var clickedOverlay = Overlays.getOverlayAtPoint({ x: event.x, y: event.y }); - if (clickedOverlay == drawButton) { - userCanDraw = !userCanDraw; - if (userCanDraw === true) { - Overlays.editOverlay(drawButton, { - color: buttonOnColor - }); - } else { - Overlays.editOverlay(drawButton, { - color: buttonOffColor - }); - } - } - if (clickedOverlay == pointerButton) { userCanPoint = !userCanPoint; if (userCanPoint === true) { Overlays.editOverlay(pointerButton, { color: buttonOnColor }); - if (userCanDraw === true) { - - Overlays.editOverlay(drawButton, { - color: buttonOnColor - }); - } } else { Overlays.editOverlay(pointerButton, { color: buttonOffColor }); - Overlays.editOverlay(drawButton, { - color: buttonOffColor - }); } } - - if (!event.isLeftButton || altHeld) { - return; - } - Controller.mouseMoveEvent.connect(mouseMoveEvent); - createOrUpdateLine(event); - lineCreated = true; } - function mouseMoveEvent(event) { createOrUpdateLine(event); } - function mouseReleaseEvent(event) { - if (!lineCreated) { + if (!event.isLeftButton) { return; } - Controller.mouseMoveEvent.disconnect(mouseMoveEvent); removeLine(); - lineCreated = false; } -function keyPressEvent(event) { - if (event.text == "ALT") { - altHeld = true; - } -} - -function keyReleaseEvent(event) { - if (event.text == "ALT") { - altHeld = false; - } - -} - -function cleanup() { - for (var i = 0; i < strokes.length; i++) { - Entities.deleteEntity(strokes[i]); - } - - Overlays.deleteOverlay(drawButton); - Overlays.deleteOverlay(pointerButton); -} - - -Script.scriptEnding.connect(cleanup); +Controller.mouseMoveEvent.connect(mouseMoveEvent); Controller.mousePressEvent.connect(mousePressEvent); -Controller.mouseReleaseEvent.connect(mouseReleaseEvent); - -Controller.keyPressEvent.connect(keyPressEvent); -Controller.keyReleaseEvent.connect(keyReleaseEvent); \ No newline at end of file +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); \ No newline at end of file From 5146e51d9ff311da0ccd5f292d5ce1c49a3b9b44 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Thu, 4 Jun 2015 16:44:46 -0700 Subject: [PATCH 25/43] improvements to avatar part clipping --- interface/src/avatar/FaceModel.cpp | 3 ++- libraries/render-utils/src/Model.cpp | 30 ++++++++++++++++++++++++---- libraries/render-utils/src/Model.h | 9 +++++++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/interface/src/avatar/FaceModel.cpp b/interface/src/avatar/FaceModel.cpp index 722f998f86..1501c52de5 100644 --- a/interface/src/avatar/FaceModel.cpp +++ b/interface/src/avatar/FaceModel.cpp @@ -39,7 +39,8 @@ void FaceModel::simulate(float deltaTime, bool fullUpdate) { setPupilDilation(_owningHead->getPupilDilation()); setBlendshapeCoefficients(_owningHead->getBlendshapeCoefficients()); - invalidCalculatedMeshBoxes(); + // FIXME - this is very expensive, we shouldn't do it if we don't have to + //invalidCalculatedMeshBoxes(); if (isActive()) { setOffset(-_geometry->getFBXGeometry().neckPivot); diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 6bb5d298f1..4bde79461c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -92,6 +92,8 @@ Model::Model(QObject* parent) : if (_viewState) { moveToThread(_viewState->getMainThread()); } + + setSnapModelToRegistrationPoint(true, glm::vec3(0.5f)); } Model::~Model() { @@ -407,7 +409,7 @@ void Model::reset() { _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes - _needsReload = true; + invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid } bool Model::updateGeometry() { @@ -459,7 +461,7 @@ bool Model::updateGeometry() { _geometry = geometry; _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes - _needsReload = true; + invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid initJointStates(newJointStates); needToRebuild = true; } else if (_jointStates.isEmpty()) { @@ -1253,6 +1255,7 @@ Extents Model::calculateScaledOffsetExtents(const Extents& extents) const { /// Returns the world space equivalent of some box in model space. AABox Model::calculateScaledOffsetAABox(const AABox& box) const { + return AABox(calculateScaledOffsetExtents(Extents(box))); } @@ -1324,6 +1327,7 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _readyWhenAdded = false; // reset out render items. _needsReload = true; + invalidCalculatedMeshBoxes(); // if we have finished reload, we need to assume our mesh boxes are all invalid _url = url; @@ -1590,6 +1594,7 @@ void Model::simulate(float deltaTime, bool fullUpdate) { || (_snapModelToRegistrationPoint && !_snappedToRegistrationPoint); if (isActive() && fullUpdate) { + // NOTE: this seems problematic... need to review _calculatedMeshBoxesValid = false; // if we have to simulate, we need to assume our mesh boxes are all invalid _calculatedMeshTrianglesValid = false; @@ -1978,6 +1983,7 @@ void Model::applyNextGeometry() { _meshGroupsKnown = false; _readyWhenAdded = false; // in case any of our users are using scenes _needsReload = false; // we are loaded now! + invalidCalculatedMeshBoxes(); _nextBaseGeometry.reset(); _nextGeometry.reset(); } @@ -2051,6 +2057,22 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran gpu::Batch& batch = *(args->_batch); auto mode = args->_renderMode; + + // render the part bounding box + #ifdef DEBUG_BOUNDING_PARTS + { + glm::vec4 cubeColor(1.0f,0.0f,0.0f,1.0f); + AABox partBounds = getPartBounds(meshIndex, partIndex); + + glm::mat4 translation = glm::translate(partBounds.calcCenter()); + glm::mat4 scale = glm::scale(partBounds.getDimensions()); + glm::mat4 modelToWorldMatrix = translation * scale; + batch.setModelTransform(modelToWorldMatrix); + //qDebug() << "partBounds:" << partBounds; + DependencyManager::get()->renderWireCube(batch, 1.0f, cubeColor); + } + #endif //def DEBUG_BOUNDING_PARTS + // Capture the view matrix once for the rendering of this model if (_transforms.empty()) { _transforms.push_back(Transform()); @@ -2094,7 +2116,7 @@ void Model::renderPart(RenderArgs* args, int meshIndex, int partIndex, bool tran if (meshIndex < 0 || meshIndex >= networkMeshes.size() || meshIndex > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes - _needsReload = true; + invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid return; // FIXME! } @@ -2410,7 +2432,7 @@ int Model::renderMeshesFromList(QVector& list, gpu::Batch& batch, RenderMod if (i < 0 || i >= networkMeshes.size() || i > geometry.meshes.size()) { _meshGroupsKnown = false; // regenerate these lists next time around. _readyWhenAdded = false; // in case any of our users are using scenes - _needsReload = true; + invalidCalculatedMeshBoxes(); // if we have to reload, we need to assume our mesh boxes are all invalid continue; } diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index ad2d725027..71fdfd9d03 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -256,7 +256,7 @@ protected: bool _snapModelToRegistrationPoint; /// is the model's offset automatically adjusted to a registration point in model space bool _snappedToRegistrationPoint; /// are we currently snapped to a registration point - glm::vec3 _registrationPoint; /// the point in model space our center is snapped to + glm::vec3 _registrationPoint = glm::vec3(0.5f); /// the point in model space our center is snapped to bool _showTrueJointTransforms; @@ -308,7 +308,12 @@ protected: float getLimbLength(int jointIndex) const; /// Allow sub classes to force invalidating the bboxes - void invalidCalculatedMeshBoxes() { _calculatedMeshBoxesValid = false; } + void invalidCalculatedMeshBoxes() { + qDebug() << "invalidCalculatedMeshBoxes()"; + _calculatedMeshBoxesValid = false; + _calculatedMeshPartBoxesValid = false; + _calculatedMeshTrianglesValid = false; + } private: From 5e15c14539947639f1c2e96b73b4c56cfc1b324f Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 16:45:32 -0700 Subject: [PATCH 26/43] added sanitization for invalid line points data. Fixed bug where occasionally wrong view frustum would be sent to script" --- interface/src/Application.cpp | 7 +++++-- .../src/RenderableLineEntityItem.cpp | 5 ++++- libraries/entities/src/LineEntityItem.cpp | 13 ++++++++++++- 3 files changed, 21 insertions(+), 4 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e800fa5ff0..e3c5d735a8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3093,8 +3093,11 @@ PickRay Application::computePickRay(float x, float y) const { if (isHMDMode()) { getApplicationOverlay().computeHmdPickRay(glm::vec2(x, y), result.origin, result.direction); } else { - auto frustum = activeRenderingThread ? getDisplayViewFrustum() : getViewFrustum(); - frustum->computePickRay(x, y, result.origin, result.direction); + if (QThread::currentThread() == activeRenderingThread) { + getDisplayViewFrustum()->computePickRay(x, y, result.origin, result.direction); + } else { + getViewFrustum()->computePickRay(x, y, result.origin, result.direction); + } } return result; } diff --git a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp index 1951b2592b..22fef37ce3 100644 --- a/libraries/entities-renderer/src/RenderableLineEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableLineEntityItem.cpp @@ -44,7 +44,10 @@ void RenderableLineEntityItem::render(RenderArgs* args) { geometryCache->updateVertices(_lineVerticesID, getLinePoints(), lineColor); _pointsChanged = false; } - geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID); + if (getLinePoints().size() > 1) { + geometryCache->renderVertices(gpu::LINE_STRIP, _lineVerticesID); + } + glPopMatrix(); RenderableDebugableEntityItem::render(this, args); diff --git a/libraries/entities/src/LineEntityItem.cpp b/libraries/entities/src/LineEntityItem.cpp index c43de8d076..0c6b73a7ce 100644 --- a/libraries/entities/src/LineEntityItem.cpp +++ b/libraries/entities/src/LineEntityItem.cpp @@ -85,7 +85,18 @@ bool LineEntityItem::setProperties(const EntityItemProperties& properties) { } void LineEntityItem::setLinePoints(const QVector& points) { - _points = points; + QVector sanitizedPoints; + for (int i = 0; i < points.size(); i++) { + glm::vec3 point = points.at(i); + // Make sure all of our points are valid numbers. + // Must be greater than 0 because vector component is set to 0 if it is invalid data + if (point.x > 0 && point.y > 0 && point.z > 0){ + sanitizedPoints << point; + } else { + qDebug() << "INVALID POINT"; + } + } + _points = sanitizedPoints; _pointsChanged = true; } From 1fd0650955295101e5cb78775f43e187ecc1bbfa Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 16:54:52 -0700 Subject: [PATCH 27/43] removing overlay on script ending --- examples/pointer.js | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/examples/pointer.js b/examples/pointer.js index 5b293c8478..cca46709ee 100644 --- a/examples/pointer.js +++ b/examples/pointer.js @@ -142,6 +142,12 @@ function mouseReleaseEvent(event) { removeLine(); } +function cleanup() { + Overlays.deleteOverlay(pointerButton); +} + +Script.scriptEnding.connect(cleanup); + Controller.mouseMoveEvent.connect(mouseMoveEvent); Controller.mousePressEvent.connect(mousePressEvent); Controller.mouseReleaseEvent.connect(mouseReleaseEvent); \ No newline at end of file From cd6bf9d46109579981dab22fa22734d6fb0e9e03 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 16:56:14 -0700 Subject: [PATCH 28/43] cleanup comments --- libraries/physics/src/PhysicalEntitySimulation.cpp | 2 +- libraries/physics/src/ShapeFactory.h | 3 --- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/libraries/physics/src/PhysicalEntitySimulation.cpp b/libraries/physics/src/PhysicalEntitySimulation.cpp index b615cf0c77..70853fb5f6 100644 --- a/libraries/physics/src/PhysicalEntitySimulation.cpp +++ b/libraries/physics/src/PhysicalEntitySimulation.cpp @@ -36,7 +36,7 @@ void PhysicalEntitySimulation::init( // begin EntitySimulation overrides void PhysicalEntitySimulation::updateEntitiesInternal(const quint64& now) { - // TODO: add back non-physical kinematic objects and step them forward here + // Do nothing here because the "internal" update the PhysicsEngine::stepSimualtion() which is done elsewhere. } void PhysicalEntitySimulation::addEntityInternal(EntityItemPointer entity) { diff --git a/libraries/physics/src/ShapeFactory.h b/libraries/physics/src/ShapeFactory.h index 699b8a0475..f6a6dfb3e6 100644 --- a/libraries/physics/src/ShapeFactory.h +++ b/libraries/physics/src/ShapeFactory.h @@ -19,11 +19,8 @@ // translates between ShapeInfo and btShape -// TODO: rename this to ShapeFactory namespace ShapeFactory { - btConvexHullShape* createConvexHull(const QVector& points); - btCollisionShape* createShapeFromInfo(const ShapeInfo& info); }; From 911baee8b84b7fc95ebaf9a99a0cb0c8e72a458e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Thu, 4 Jun 2015 16:57:29 -0700 Subject: [PATCH 29/43] fix for crash during bogus reconnect on login --- libraries/physics/src/PhysicsEngine.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 1f0a4edfb8..deb8d46474 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -153,11 +153,11 @@ void PhysicsEngine::deleteObjects(VectorOfMotionStates& objects) { } } -// Same as above, but takes a Set instead of a Vector and ommits some cleanup operations. Only called during teardown. +// Same as above, but takes a Set instead of a Vector. Should only be called during teardown. void PhysicsEngine::deleteObjects(SetOfMotionStates& objects) { for (auto object : objects) { btRigidBody* body = object->getRigidBody(); - _dynamicsWorld->removeRigidBody(body); + removeObject(object); // NOTE: setRigidBody() modifies body->m_userPointer so we should clear the MotionState's body BEFORE deleting it. object->setRigidBody(nullptr); From 241330442c1575bc69dcceab4df590cf6f66d746 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 17:35:26 -0700 Subject: [PATCH 30/43] added paint.js and line rider script. Users can paint lines with hydra or mouse, and then go on a ride over the line they just created. --- examples/lineRider.js | 117 +++++++++++ examples/paint.js | 478 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 595 insertions(+) create mode 100644 examples/lineRider.js create mode 100644 examples/paint.js diff --git a/examples/lineRider.js b/examples/lineRider.js new file mode 100644 index 0000000000..21a690fc63 --- /dev/null +++ b/examples/lineRider.js @@ -0,0 +1,117 @@ +// +// lineRider.js +// examples +// +// Created by Eric Levin on 6/4/15. +// Copyright 2014 High Fidelity, Inc. +// +// Takes the avatar on a line ride. Meant to be used in conjunction with paint.js +// Paint a line and then click on roller coaster icon to start! +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +LineRider = function() { + HIFI_PUBLIC_BUCKET = "http://s3.amazonaws.com/hifi-public/"; + var screenSize = Controller.getViewportDimensions(); + + var BUTTON_SIZE = 32; + var PADDING = 3; + + this.buttonOffColor = { + red: 250, + green: 10, + blue: 10 + }; + this.buttonOnColor = { + red: 10, + green: 200, + blue: 100 + }; + this.riding = false; + + this.startButton = Overlays.addOverlay("image", { + x: screenSize.x / 2 - BUTTON_SIZE + PADDING * 2, + y: screenSize.y - (BUTTON_SIZE + PADDING), + width: BUTTON_SIZE, + height: BUTTON_SIZE, + imageURL: HIFI_PUBLIC_BUCKET + "images/coaster.png?v2", + color: this.buttonOffColor, + alpha: 1 + }); + + this.currentPoint = 0; + this.shouldUpdate = false; + this.moveIntervalTime = 50; + +} + + +LineRider.prototype.move = function() { + if (!this.shouldMove) { + return; + } + MyAvatar.position = this.points[this.currentPoint++]; + + if (this.currentPoint === this.points.length) { + this.currentPoint = 0; + } + var self = this; + Script.setTimeout(function() { + self.move(); + }, this.moveIntervalTime); +} + +LineRider.prototype.setPath = function(points) { + this.points = points; +} + +LineRider.prototype.addStartHandler = function(callback) { + this.onStart = callback; +} + + +LineRider.prototype.mousePressEvent = function(event) { + var clickedOverlay = Overlays.getOverlayAtPoint({ + x: event.x, + y: event.y + }); + if (clickedOverlay == this.startButton) { + this.toggleRide(); + + } + +} + +LineRider.prototype.toggleRide = function() { + this.riding = !this.riding; + if (this.riding === true) { + Overlays.editOverlay(this.startButton, { + color: this.buttonOnColor + }); + if (this.onStart) { + this.onStart(); + //make sure we actually have a path + if (this.points.length > 2) { + this.shouldMove = true; + } + var self = this; + Script.setTimeout(function() { + self.move(); + }, this.moveIntervalTime); + } + } else { + Overlays.editOverlay(this.startButton, { + color: this.buttonOffColor + }) + this.shouldMove = false; + } + +} +LineRider.prototype.startRide = function() { + this.shouldUpdate = true; + +} + +LineRider.prototype.cleanup = function() { + Overlays.deleteOverlay(this.startButton); +} \ No newline at end of file diff --git a/examples/paint.js b/examples/paint.js new file mode 100644 index 0000000000..9a774a1442 --- /dev/null +++ b/examples/paint.js @@ -0,0 +1,478 @@ +// +// paint.js +// examples +// +// Created by Eric Levin on 6/4/15. +// Copyright 2014 High Fidelity, Inc. +// +// This script allows you to paint with the hydra or mouse! +// +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +Script.include('lineRider.js') +var MAX_POINTS_PER_LINE = 30; +var DRAWING_DISTANCE = 5; + +var colorPalette = [{ + red: 236, + green: 208, + blue: 120 +}, { + red: 217, + green: 91, + blue: 67 +}, { + red: 192, + green: 41, + blue: 66 +}, { + red: 84, + green: 36, + blue: 55 +}, { + red: 83, + green: 119, + blue: 122 +}]; + +var currentColorIndex = 0; +var currentColor = colorPalette[currentColorIndex]; + + + +if (hydraCheck() === true) { + HydraPaint(); +} else { + MousePaint(); +} + + +function cycleColor() { + currentColor = colorPalette[++currentColorIndex]; + if (currentColorIndex === colorPalette.length - 1) { + currentColorIndex = -1; + } + +} + +function hydraCheck() { + var numberOfButtons = Controller.getNumberOfButtons(); + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + hydrasConnected = (numberOfButtons == 12 && numberOfTriggers == 2 && controllersPerTrigger == 2); + return hydrasConnected; //hydrasConnected; +} + + +function MousePaint() { + var lines = []; + var isDrawing = false; + var path = []; + + var lineRider = new LineRider(); + lineRider.addStartHandler(function() { + var points = []; + //create points array from list of all points in path + path.forEach(function(point) { + points.push(point); + }); + lineRider.setPath(points); + }); + + + + var LINE_WIDTH = 7; + var line; + var points = []; + + + var BRUSH_SIZE = 0.08; + + var brush = Entities.addEntity({ + type: 'Sphere', + position: { + x: 0, + y: 0, + z: 0 + }, + color: currentColor, + dimensions: { + x: BRUSH_SIZE, + y: BRUSH_SIZE, + z: BRUSH_SIZE + } + }); + + + function newLine(point) { + line = Entities.addEntity({ + position: MyAvatar.position, + type: "Line", + color: currentColor, + dimensions: { + x: 10, + y: 10, + z: 10 + }, + lineWidth: LINE_WIDTH + }); + points = []; + if (point) { + points.push(point); + path.push(point); + } + lines.push(line); + } + + + function mouseMoveEvent(event) { + if (!isDrawing) { + return; + } + + + var pickRay = Camera.computePickRay(event.x, event.y); + var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); + var point = Vec3.sum(Camera.getPosition(), addVector); + points.push(point); + Entities.editEntity(line, { + linePoints: points + }); + Entities.editEntity(brush, { + position: point + }); + path.push(point); + + if (points.length === MAX_POINTS_PER_LINE) { + //We need to start a new line! + newLine(point); + } + } + + function mousePressEvent(event) { + lineRider.mousePressEvent(event); + path = []; + newLine(); + isDrawing = true; + + + } + + function mouseReleaseEvent() { + isDrawing = false; + } + + function keyPressEvent(event) { + if (event.text === "SPACE") { + cycleColor(); + Entities.editEntity(brush, { + color: currentColor + }); + } + } + + function cleanup() { + lines.forEach(function(line) { + Entities.deleteEntity(line); + }); + Entities.deleteEntity(brush); + + } + + + Controller.mousePressEvent.connect(mousePressEvent); + Controller.mouseReleaseEvent.connect(mouseReleaseEvent); + Controller.mouseMoveEvent.connect(mouseMoveEvent); + Script.scriptEnding.connect(cleanup); + + function randFloat(low, high) { + return Math.floor(low + Math.random() * (high - low)); + } + + + function randInt(low, high) { + return Math.floor(randFloat(low, high)); + } + + Controller.keyPressEvent.connect(keyPressEvent); +} + + + +//*****************HYDRA PAINT ******************************************* + + + + +function HydraPaint() { + + + + var lineRider = new LineRider(); + lineRider.addStartHandler(function() { + var points = []; + //create points array from list of all points in path + rightController.path.forEach(function(point) { + points.push(point); + }); + lineRider.setPath(points); + }); + + var LEFT = 0; + var RIGHT = 1; + + var currentTime = 0; + + + var DISTANCE_FROM_HAND = 2; + var minBrushSize = .02; + var maxBrushSize = .04 + + + var minLineWidth = 5; + var maxLineWidth = 10; + var currentLineWidth = minLineWidth; + var MIN_PAINT_TRIGGER_THRESHOLD = .01; + var LINE_LIFETIME = 20; + var COLOR_CHANGE_TIME_FACTOR = 0.1; + + var RIGHT_BUTTON_1 = 7 + var RIGHT_BUTTON_2 = 8 + var RIGHT_BUTTON_3 = 9; + var RIGHT_BUTTON_4 = 10 + + var LEFT_BUTTON_1 = 1; + var LEFT_BUTTON_2 = 2; + var LEFT_BUTTON_3 = 3; + var LEFT_BUTTON_4 = 4; + + var STROKE_SMOOTH_FACTOR = 1; + + var MIN_DRAW_DISTANCE = 1; + var MAX_DRAW_DISTANCE = 2; + + function controller(side, undoButton, redoButton, cycleColorButton, startRideButton) { + this.triggerHeld = false; + this.triggerThreshold = 0.9; + this.side = side; + this.palm = 2 * side; + this.tip = 2 * side + 1; + this.trigger = side; + this.lines = []; + this.deletedLines = [] //just an array of properties objects + this.isPainting = false; + + this.undoButton = undoButton; + this.undoButtonPressed = false; + this.prevUndoButtonPressed = false; + + this.redoButton = redoButton; + this.redoButtonPressed = false; + this.prevRedoButtonPressed = false; + + this.cycleColorButton = cycleColorButton; + this.cycleColorButtonPressed = false; + this.prevColorCycleButtonPressed = false; + + this.startRideButton = startRideButton; + this.startRideButtonPressed = false; + this.prevStartRideButtonPressed = false; + + this.strokeCount = 0; + this.currentBrushSize = minBrushSize; + this.points = []; + this.path = []; + + this.brush = Entities.addEntity({ + type: 'Sphere', + position: { + x: 0, + y: 0, + z: 0 + }, + color: currentColor, + dimensions: { + x: minBrushSize, + y: minBrushSize, + z: minBrushSize + } + }); + + + this.newLine = function(point) { + this.line = Entities.addEntity({ + position: MyAvatar.position, + type: "Line", + color: currentColor, + dimensions: { + x: 10, + y: 10, + z: 10 + }, + lineWidth: 5, + // lifetime: LINE_LIFETIME + }); + this.points = []; + if (point) { + this.points.push(point); + this.path.push(point); + } + this.lines.push(this.line); + } + + this.update = function(deltaTime) { + this.updateControllerState(); + this.avatarPalmOffset = Vec3.subtract(this.palmPosition, MyAvatar.position); + this.projectedForwardDistance = Vec3.dot(Quat.getFront(Camera.getOrientation()), this.avatarPalmOffset); + this.mappedPalmOffset = map(this.projectedForwardDistance, -.5, .5, MIN_DRAW_DISTANCE, MAX_DRAW_DISTANCE); + this.tipDirection = Vec3.normalize(Vec3.subtract(this.tipPosition, this.palmPosition)); + this.offsetVector = Vec3.multiply(this.mappedPalmOffset, this.tipDirection); + this.drawPoint = Vec3.sum(this.palmPosition, this.offsetVector); + this.currentBrushSize = map(this.triggerValue, 0, 1, minBrushSize, maxBrushSize); + Entities.editEntity(this.brush, { + position: this.drawPoint, + dimensions: { + x: this.currentBrushSize, + y: this.currentBrushSize, + z: this.currentBrushSize + }, + color: currentColor + }); + if (this.triggerValue > MIN_PAINT_TRIGGER_THRESHOLD) { + if (!this.isPainting) { + this.isPainting = true; + this.newLine(); + this.path = []; + } + if (this.strokeCount % STROKE_SMOOTH_FACTOR === 0) { + this.paint(this.drawPoint); + } + this.strokeCount++; + } else if (this.triggerValue < MIN_PAINT_TRIGGER_THRESHOLD && this.isPainting) { + this.releaseTrigger(); + } + + this.oldPalmPosition = this.palmPosition; + this.oldTipPosition = this.tipPosition; + } + + this.releaseTrigger = function() { + this.isPainting = false; + + } + + + this.updateControllerState = function() { + this.undoButtonPressed = Controller.isButtonPressed(this.undoButton); + this.redoButtonPressed = Controller.isButtonPressed(this.redoButton); + this.cycleColorButtonPressed = Controller.isButtonPressed(this.cycleColorButton); + this.startRideButtonPressed = Controller.isButtonPressed(this.startRideButton); + + //This logic gives us button release + if (this.prevUndoButtonPressed === true && this.undoButtonPressed === false) { + //User released undo button, so undo + this.undoStroke(); + } + if (this.prevRedoButtonPressed === true && this.redoButtonPressed === false) { + this.redoStroke(); + } + + if (this.prevCycleColorButtonPressed === true && this.cycleColorButtonPressed === false) { + cycleColor(); + Entities.editEntity(this.brush, { + color: currentColor + }); + } + if (this.prevStartRideButtonPressed === true && this.startRideButtonPressed === false) { + lineRider.toggleRide(); + } + this.prevRedoButtonPressed = this.redoButtonPressed; + this.prevUndoButtonPressed = this.undoButtonPressed; + this.prevCycleColorButtonPressed = this.cycleColorButtonPressed; + this.prevStartRideButtonPressed = this.startRideButtonPressed; + + this.palmPosition = Controller.getSpatialControlPosition(this.palm); + this.tipPosition = Controller.getSpatialControlPosition(this.tip); + this.triggerValue = Controller.getTriggerValue(this.trigger); + } + + this.undoStroke = function() { + var deletedLine = this.lines.pop(); + var deletedLineProps = Entities.getEntityProperties(deletedLine); + this.deletedLines.push(deletedLineProps); + Entities.deleteEntity(deletedLine); + } + + this.redoStroke = function() { + var restoredLine = Entities.addEntity(this.deletedLines.pop()); + Entities.addEntity(restoredLine); + this.lines.push(restoredLine); + } + + this.paint = function(point) { + + currentLineWidth = map(this.triggerValue, 0, 1, minLineWidth, maxLineWidth); + this.points.push(point); + this.path.push(point); + Entities.editEntity(this.line, { + linePoints: this.points, + lineWidth: currentLineWidth, + color: this.rgbColor + }); + if (this.points.length > MAX_POINTS_PER_LINE) { + this.newLine(point); + } + } + + this.cleanup = function() { + Entities.deleteEntity(this.brush); + this.lines.forEach(function(line) { + Entities.deleteEntity(line); + }); + } + } + + function update(deltaTime) { + rightController.update(deltaTime); + leftController.update(deltaTime); + currentTime += deltaTime; + } + + function scriptEnding() { + rightController.cleanup(); + leftController.cleanup(); + lineRider.cleanup(); + } + + function mousePressEvent(event) { + lineRider.mousePressEvent(event); + } + + function vectorIsZero(v) { + return v.x === 0 && v.y === 0 && v.z === 0; + } + + + var rightController = new controller(RIGHT, RIGHT_BUTTON_3, RIGHT_BUTTON_4, RIGHT_BUTTON_1, RIGHT_BUTTON_2); + var leftController = new controller(LEFT, LEFT_BUTTON_3, LEFT_BUTTON_4, LEFT_BUTTON_1, LEFT_BUTTON_2); + + Script.update.connect(update); + Script.scriptEnding.connect(scriptEnding); + Controller.mousePressEvent.connect(mousePressEvent); + + function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); + } + + function randFloat(low, high) { + return Math.floor(low + Math.random() * (high - low)); + } + + + function randInt(low, high) { + return Math.floor(randFloat(low, high)); + } +} \ No newline at end of file From f276ca30cd9c656d690409348d5cab1cbae41559 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 17:55:55 -0700 Subject: [PATCH 31/43] refactoring for common functions. Fix for randFloat --- examples/paint.js | 21 ++++++--------------- 1 file changed, 6 insertions(+), 15 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 9a774a1442..670ffe047c 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -188,15 +188,6 @@ function MousePaint() { Controller.mouseMoveEvent.connect(mouseMoveEvent); Script.scriptEnding.connect(cleanup); - function randFloat(low, high) { - return Math.floor(low + Math.random() * (high - low)); - } - - - function randInt(low, high) { - return Math.floor(randFloat(low, high)); - } - Controller.keyPressEvent.connect(keyPressEvent); } @@ -420,7 +411,6 @@ function HydraPaint() { Entities.editEntity(this.line, { linePoints: this.points, lineWidth: currentLineWidth, - color: this.rgbColor }); if (this.points.length > MAX_POINTS_PER_LINE) { this.newLine(point); @@ -463,16 +453,17 @@ function HydraPaint() { Script.scriptEnding.connect(scriptEnding); Controller.mousePressEvent.connect(mousePressEvent); - function map(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); - } +} function randFloat(low, high) { - return Math.floor(low + Math.random() * (high - low)); + return low + Math.random() * ( high - low ); } function randInt(low, high) { return Math.floor(randFloat(low, high)); } -} \ No newline at end of file + + function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); + } \ No newline at end of file From 9264ef980c4d29d731571478f42481895258dfa9 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 21:13:16 -0700 Subject: [PATCH 32/43] added redo and undo functionality to mouse component of paint script, and fixed overlay not being deleted on script ending bug --- examples/paint.js | 47 ++++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 670ffe047c..787e9156bc 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -66,11 +66,13 @@ function hydraCheck() { return hydrasConnected; //hydrasConnected; } +//************ Mouse Paint ************************** function MousePaint() { var lines = []; + var deletedLines = []; var isDrawing = false; - var path = []; + var path = []; var lineRider = new LineRider(); lineRider.addStartHandler(function() { @@ -152,6 +154,19 @@ function MousePaint() { } } + function undoStroke() { + var deletedLine = lines.pop(); + var deletedLineProps = Entities.getEntityProperties(deletedLine); + deletedLines.push(deletedLineProps); + Entities.deleteEntity(deletedLine); + } + + function redoStroke() { + var restoredLine = Entities.addEntity(deletedLines.pop()); + Entities.addEntity(restoredLine); + lines.push(restoredLine); + } + function mousePressEvent(event) { lineRider.mousePressEvent(event); path = []; @@ -172,6 +187,12 @@ function MousePaint() { color: currentColor }); } + if (event.text === "z") { + undoStroke(); + } + if(event.text === "x") { + redoStroke(); + } } function cleanup() { @@ -179,6 +200,7 @@ function MousePaint() { Entities.deleteEntity(line); }); Entities.deleteEntity(brush); + lineRider.cleanup(); } @@ -197,7 +219,6 @@ function MousePaint() { - function HydraPaint() { @@ -431,7 +452,7 @@ function HydraPaint() { currentTime += deltaTime; } - function scriptEnding() { + function cleanup() { rightController.cleanup(); leftController.cleanup(); lineRider.cleanup(); @@ -450,20 +471,20 @@ function HydraPaint() { var leftController = new controller(LEFT, LEFT_BUTTON_3, LEFT_BUTTON_4, LEFT_BUTTON_1, LEFT_BUTTON_2); Script.update.connect(update); - Script.scriptEnding.connect(scriptEnding); + Script.scriptEnding.connect(cleanup); Controller.mousePressEvent.connect(mousePressEvent); } - function randFloat(low, high) { - return low + Math.random() * ( high - low ); - } +function randFloat(low, high) { + return low + Math.random() * (high - low); +} - function randInt(low, high) { - return Math.floor(randFloat(low, high)); - } +function randInt(low, high) { + return Math.floor(randFloat(low, high)); +} - function map(value, min1, max1, min2, max2) { - return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); - } \ No newline at end of file +function map(value, min1, max1, min2, max2) { + return min2 + (max2 - min2) * ((value - min1) / (max1 - min1)); +} \ No newline at end of file From fd8126510d15d1c38f0e0354c40c5525f6980349 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Thu, 4 Jun 2015 21:41:19 -0700 Subject: [PATCH 33/43] marker ball now stays without mouse whether or not user is drawing --- examples/paint.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 787e9156bc..837b217797 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -131,21 +131,22 @@ function MousePaint() { function mouseMoveEvent(event) { - if (!isDrawing) { - return; - } var pickRay = Camera.computePickRay(event.x, event.y); var addVector = Vec3.multiply(Vec3.normalize(pickRay.direction), DRAWING_DISTANCE); var point = Vec3.sum(Camera.getPosition(), addVector); - points.push(point); Entities.editEntity(line, { linePoints: points }); Entities.editEntity(brush, { position: point }); + if (!isDrawing) { + return; + } + + points.push(point); path.push(point); if (points.length === MAX_POINTS_PER_LINE) { @@ -168,6 +169,10 @@ function MousePaint() { } function mousePressEvent(event) { + if(!event.isLeftButton) { + isDrawing = false; + return; + } lineRider.mousePressEvent(event); path = []; newLine(); From f19c0d8eecb589ca3c88753bd36ff63f6e826883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20Brisset?= Date: Fri, 5 Jun 2015 13:23:58 +0100 Subject: [PATCH 34/43] Some renaming for windows compiler --- libraries/render/src/render/DrawTask.cpp | 8 ++++---- libraries/shared/src/RenderArgs.h | 22 +++++++++++----------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 8011b3a715..c0a1639f8b 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -241,9 +241,9 @@ template <> void render::jobRun(const DrawOpaque& job, const SceneContextPointer ItemIDs culledItems; if (renderContext->_cullOpaque) { - renderDetails.pointTo(RenderDetails::OPAQUE); + renderDetails.pointTo(RenderDetails::OPAQUE_ITEM); cullItems(sceneContext, renderContext, renderedItems, culledItems); - renderDetails.pointTo(RenderDetails::OTHER); + renderDetails.pointTo(RenderDetails::OTHER_ITEM); renderedItems = culledItems; } @@ -307,9 +307,9 @@ template <> void render::jobRun(const DrawTransparent& job, const SceneContextPo ItemIDs culledItems; if (renderContext->_cullTransparent) { - renderDetails.pointTo(RenderDetails::TRANSLUCENT); + renderDetails.pointTo(RenderDetails::TRANSLUCENT_ITEM); cullItems(sceneContext, renderContext, inItems, culledItems); - renderDetails.pointTo(RenderDetails::OTHER); + renderDetails.pointTo(RenderDetails::OTHER_ITEM); renderedItems = culledItems; } diff --git a/libraries/shared/src/RenderArgs.h b/libraries/shared/src/RenderArgs.h index cdfdfb9c5f..84b3a202b4 100644 --- a/libraries/shared/src/RenderArgs.h +++ b/libraries/shared/src/RenderArgs.h @@ -25,12 +25,12 @@ class Context; class RenderDetails { public: enum Type { - OPAQUE, - TRANSLUCENT, - OTHER + OPAQUE_ITEM, + TRANSLUCENT_ITEM, + OTHER_ITEM }; - struct Items { + struct Item { int _considered = 0; int _rendered = 0; int _outOfView = 0; @@ -41,21 +41,21 @@ public: int _trianglesRendered = 0; int _quadsRendered = 0; - Items _opaque; - Items _translucent; - Items _other; + Item _opaque; + Item _translucent; + Item _other; - Items* _item = &_other; + Item* _item = &_other; void pointTo(Type type) { switch (type) { - case OPAQUE: + case OPAQUE_ITEM: _item = &_opaque; break; - case TRANSLUCENT: + case TRANSLUCENT_ITEM: _item = &_translucent; break; - case OTHER: + case OTHER_ITEM: _item = &_other; break; } From 260272d2881e4a0732eb2c3b6f072576591d6cdd Mon Sep 17 00:00:00 2001 From: Atlante45 Date: Fri, 5 Jun 2015 14:32:47 +0200 Subject: [PATCH 35/43] Transform to polyvox corner for render --- .../entities-renderer/src/RenderablePolyVoxEntityItem.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp index 4d85e73bcc..41c2799d97 100644 --- a/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderablePolyVoxEntityItem.cpp @@ -380,14 +380,16 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) { getModel(); } - Transform transformToCenter = getTransformToCenter(); - transformToCenter.setScale(getDimensions() / _voxelVolumeSize); + Transform transform; + transform.setTranslation(getPosition() - getRegistrationPoint() * getDimensions()); + transform.setRotation(getRotation()); + transform.setScale(getDimensions() / _voxelVolumeSize); auto mesh = _modelGeometry.getMesh(); Q_ASSERT(args->_batch); gpu::Batch& batch = *args->_batch; DependencyManager::get()->bindSimpleProgram(batch); - batch.setModelTransform(transformToCenter); + batch.setModelTransform(transform); batch.setInputFormat(mesh->getVertexFormat()); batch.setInputBuffer(gpu::Stream::POSITION, mesh->getVertexBuffer()); batch.setInputBuffer(gpu::Stream::NORMAL, From 9cb7cb314dcc0a96680586f2d21650e2da579217 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 5 Jun 2015 08:43:48 -0700 Subject: [PATCH 36/43] update minimum version support --- libraries/entities/src/EntityTree.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 0d99c8e82d..5897d3e9a8 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -64,7 +64,7 @@ public: virtual bool getWantSVOfileVersions() const { return true; } virtual PacketType expectedDataPacketType() const { return PacketTypeEntityData; } virtual bool canProcessVersion(PacketVersion thisVersion) const - { return thisVersion >= VERSION_ENTITIES_SUPPORT_SPLIT_MTU; } // we support all versions with split mtu + { return thisVersion >= VERSION_ENTITIES_USE_METERS_AND_RADIANS; } virtual bool handlesEditPacketType(PacketType packetType) const; virtual int processEditPacketData(PacketType packetType, const unsigned char* packetData, int packetLength, const unsigned char* editData, int maxLength, const SharedNodePointer& senderNode); From 9814d11beaa8d696cb44231c2ad35f6f95508d13 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Jun 2015 08:45:31 -0700 Subject: [PATCH 37/43] Fix model entities correctly updating payloads when url changes --- .../entities-renderer/src/RenderableModelEntityItem.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index 81ddb912cc..0b0a7da398 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -212,6 +212,11 @@ void RenderableModelEntityItem::render(RenderArgs* args) { if (hasModel()) { if (_model) { + if (QUrl(getModelURL()) != _model->getURL()) { + qDebug() << "Updating model URL: " << getModelURL(); + _model->setURL(getModelURL()); + } + // check to see if when we added our models to the scene they were ready, if they were not ready, then // fix them up in the scene render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene(); From d60810e221a5f684f72301050aa306b3c24d150b Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Jun 2015 09:10:38 -0700 Subject: [PATCH 38/43] CR feedback --- libraries/render-utils/src/Model.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 4bde79461c..55242a6cef 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -1327,7 +1327,6 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo _readyWhenAdded = false; // reset out render items. _needsReload = true; - invalidCalculatedMeshBoxes(); // if we have finished reload, we need to assume our mesh boxes are all invalid _url = url; From 30ba7ffc295dd1dc2468a2a3a38dcddd92c2e398 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 5 Jun 2015 09:36:12 -0700 Subject: [PATCH 39/43] moved ball marker closer to hand so painting feels more visceral --- examples/paint.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 837b217797..97b71db67b 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -244,7 +244,6 @@ function HydraPaint() { var currentTime = 0; - var DISTANCE_FROM_HAND = 2; var minBrushSize = .02; var maxBrushSize = .04 @@ -268,8 +267,8 @@ function HydraPaint() { var STROKE_SMOOTH_FACTOR = 1; - var MIN_DRAW_DISTANCE = 1; - var MAX_DRAW_DISTANCE = 2; + var MIN_DRAW_DISTANCE = 0.2; + var MAX_DRAW_DISTANCE = 0.4; function controller(side, undoButton, redoButton, cycleColorButton, startRideButton) { this.triggerHeld = false; From 16f55c75572d64f9fc77a87be17619335c5206bc Mon Sep 17 00:00:00 2001 From: Brad Davis Date: Fri, 5 Jun 2015 09:52:56 -0700 Subject: [PATCH 40/43] Fix the skybox jiggle in the HMD --- interface/src/Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index e3c5d735a8..2b6ec63d4b 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -3314,7 +3314,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, bool billb skybox = skyStage->getSkybox(); if (skybox) { gpu::Batch batch; - model::Skybox::render(batch, _viewFrustum, *skybox); + model::Skybox::render(batch, _displayViewFrustum, *skybox); gpu::GLBackend::renderBatch(batch); glUseProgram(0); From 9f974c3b5c62f0fe600f9e51821032bba9425735 Mon Sep 17 00:00:00 2001 From: Eric Levin Date: Fri, 5 Jun 2015 10:19:39 -0700 Subject: [PATCH 41/43] moves ball marker closer to avatar for mouse as well --- examples/paint.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/examples/paint.js b/examples/paint.js index 97b71db67b..6e4438d2ea 100644 --- a/examples/paint.js +++ b/examples/paint.js @@ -13,7 +13,7 @@ // Script.include('lineRider.js') var MAX_POINTS_PER_LINE = 30; -var DRAWING_DISTANCE = 5; + var colorPalette = [{ red: 236, @@ -69,6 +69,7 @@ function hydraCheck() { //************ Mouse Paint ************************** function MousePaint() { + var DRAWING_DISTANCE = 2; var lines = []; var deletedLines = []; var isDrawing = false; @@ -91,7 +92,7 @@ function MousePaint() { var points = []; - var BRUSH_SIZE = 0.08; + var BRUSH_SIZE = 0.02; var brush = Entities.addEntity({ type: 'Sphere', From 37d93941404ca036cd40754e33eed41482a53ef1 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Fri, 5 Jun 2015 10:26:09 -0700 Subject: [PATCH 42/43] Fix entity payloads not being removed on delete --- libraries/entities-renderer/src/EntityTreeRenderer.cpp | 7 +++---- libraries/entities-renderer/src/EntityTreeRenderer.h | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.cpp b/libraries/entities-renderer/src/EntityTreeRenderer.cpp index 76646109fb..8f18054f52 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.cpp +++ b/libraries/entities-renderer/src/EntityTreeRenderer.cpp @@ -1000,13 +1000,12 @@ void EntityTreeRenderer::deletingEntity(const EntityItemID& entityID) { _entityScripts.remove(entityID); // here's where we remove the entity payload from the scene - auto entity = static_cast(_tree)->findEntityByID(entityID); - if (entity && _entitiesInScene.contains(entity)) { + if (_entitiesInScene.contains(entityID)) { + auto entity = _entitiesInScene.take(entityID); render::PendingChanges pendingChanges; auto scene = _viewState->getMain3DScene(); entity->removeFromScene(entity, scene, pendingChanges); scene->enqueuePendingChanges(pendingChanges); - _entitiesInScene.remove(entity); } } @@ -1021,7 +1020,7 @@ void EntityTreeRenderer::addEntityToScene(EntityItemPointer entity) { render::PendingChanges pendingChanges; auto scene = _viewState->getMain3DScene(); if (entity->addToScene(entity, scene, pendingChanges)) { - _entitiesInScene.insert(entity); + _entitiesInScene.insert(entity->getEntityItemID(), entity); } scene->enqueuePendingChanges(pendingChanges); } diff --git a/libraries/entities-renderer/src/EntityTreeRenderer.h b/libraries/entities-renderer/src/EntityTreeRenderer.h index 55c889d1c1..e491524c78 100644 --- a/libraries/entities-renderer/src/EntityTreeRenderer.h +++ b/libraries/entities-renderer/src/EntityTreeRenderer.h @@ -188,7 +188,7 @@ private: float _previousStageHour; int _previousStageDay; - QSet _entitiesInScene; + QHash _entitiesInScene; }; From 35f40df6e283b3ef8e2884c5660d9f3e4032058c Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Fri, 5 Jun 2015 12:06:13 -0700 Subject: [PATCH 43/43] fix build buster --- libraries/entities-renderer/src/RenderableWebEntityItem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index f83b012133..3d284baab6 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -169,7 +169,7 @@ void RenderableWebEntityItem::render(RenderArgs* args) { _webSurface->resize(QSize(dims.x, dims.y)); currentContext->makeCurrent(currentSurface); - Glower glow(0); + Glower glow(0.0f); PerformanceTimer perfTimer("RenderableWebEntityItem::render"); Q_ASSERT(getType() == EntityTypes::Web); static const glm::vec2 texMin(0.0f);