diff --git a/assignment-client/src/avatars/AvatarMixer.cpp b/assignment-client/src/avatars/AvatarMixer.cpp index 176fd51eea..dae6af3fc5 100644 --- a/assignment-client/src/avatars/AvatarMixer.cpp +++ b/assignment-client/src/avatars/AvatarMixer.cpp @@ -149,7 +149,8 @@ void AvatarMixer::broadcastAvatarData() { // about a given otherNode to this node // FIXME does this mean we should sort the othernodes by distance before iterating // over them? - float outputBandwidth = node->getOutboundBandwidth(); + // float outputBandwidth = + node->getOutboundBandwidth(); // this is an AGENT we have received head data from // send back a packet with other active node data to this node @@ -169,7 +170,7 @@ void AvatarMixer::broadcastAvatarData() { return true; }, [&](const SharedNodePointer& otherNode) { - AvatarMixerClientData* otherNodeData = otherNodeData = reinterpret_cast(otherNode->getLinkedData()); + AvatarMixerClientData* otherNodeData = reinterpret_cast(otherNode->getLinkedData()); MutexTryLocker lock(otherNodeData->getMutex()); if (!lock.isLocked()) { return; diff --git a/examples/edit.js b/examples/edit.js index 2529b617d9..1ea7647a54 100644 --- a/examples/edit.js +++ b/examples/edit.js @@ -718,13 +718,8 @@ function mouseClickEvent(event) { var result = findClickedEntity(event); if (result) { var properties = Entities.getEntityProperties(result.entityID); - var data = {}; - try { - data = JSON.parse(properties.attribution); - } catch (e) { - } - if (data.marketplaceID) { - propertyMenu.marketplaceID = data.marketplaceID; + if (properties.marketplaceID) { + propertyMenu.marketplaceID = properties.marketplaceID; propertyMenu.updateMenuItemText(showMenuItem, "Show in Marketplace"); } else { propertyMenu.marketplaceID = null; diff --git a/examples/html/entityProperties.html b/examples/html/entityProperties.html index dc632d76fd..596bf5c9d5 100644 --- a/examples/html/entityProperties.html +++ b/examples/html/entityProperties.html @@ -140,7 +140,6 @@ var elLifetime = document.getElementById("property-lifetime"); var elScriptURL = document.getElementById("property-script-url"); var elUserData = document.getElementById("property-user-data"); - var elAttribution = document.getElementById("property-attribution"); var elBoxSections = document.querySelectorAll(".box-section"); var elBoxColorRed = document.getElementById("property-box-red"); @@ -264,7 +263,6 @@ elLifetime.value = properties.lifetime; elScriptURL.value = properties.script; elUserData.value = properties.userData; - elAttribution.value = properties.attribution; if (properties.type != "Box") { for (var i = 0; i < elBoxSections.length; i++) { @@ -395,7 +393,6 @@ elLifetime.addEventListener('change', createEmitNumberPropertyUpdateFunction('lifetime')); elScriptURL.addEventListener('change', createEmitTextPropertyUpdateFunction('script')); elUserData.addEventListener('change', createEmitTextPropertyUpdateFunction('userData')); - elAttribution.addEventListener('change', createEmitTextPropertyUpdateFunction('attribution')); var boxColorChangeFunction = createEmitColorPropertyUpdateFunction( 'color', elBoxColorRed, elBoxColorGreen, elBoxColorBlue); @@ -630,13 +627,6 @@ -
-
Attribution
-
- -
-
-
Color
diff --git a/examples/notifications.js b/examples/notifications.js index 7e56c1b50d..5ee6874521 100644 --- a/examples/notifications.js +++ b/examples/notifications.js @@ -92,11 +92,13 @@ var NotificationType = { SNAPSHOT: 2, WINDOW_RESIZE: 3, LOD_WARNING: 4, + CONNECTION_REFUSED: 5, properties: [ { text: "Mute Toggle" }, { text: "Snapshot" }, { text: "Window Resize" }, - { text: "Level of Detail" } + { text: "Level of Detail" }, + { text: "Connection Refused" } ], getTypeFromMenuItem: function(menuItemName) { if (menuItemName.substr(menuItemName.length - NOTIFICATION_MENU_ITEM_POST.length) !== NOTIFICATION_MENU_ITEM_POST) { @@ -501,6 +503,10 @@ function onMuteStateChanged() { createNotification(muteString, NotificationType.MUTE_TOGGLE); } +function onDomainConnectionRefused(reason) { + createNotification("Connection refused: " + reason, NotificationType.CONNECTION_REFUSED ); +} + // handles mouse clicks on buttons function mousePressEvent(event) { var pickRay, @@ -608,5 +614,6 @@ Controller.keyReleaseEvent.connect(keyReleaseEvent); Script.update.connect(update); Script.scriptEnding.connect(scriptEnding); Menu.menuItemEvent.connect(menuItemEvent); +Window.domainConnectionRefused.connect(onDomainConnectionRefused); setup(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 99777d22bf..5753449075 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -297,7 +297,8 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : _lastSendDownstreamAudioStats(usecTimestampNow()), _isVSyncOn(true), _aboutToQuit(false), - _notifiedPacketVersionMismatchThisDomain(false) + _notifiedPacketVersionMismatchThisDomain(false), + _domainConnectionRefusals(QList()) { #ifdef Q_OS_WIN installNativeEventFilter(&MyNativeEventFilter::getInstance()); @@ -344,6 +345,13 @@ Application::Application(int& argc, char** argv, QElapsedTimer &startup_time) : // put the NodeList and datagram processing on the node thread nodeList->moveToThread(nodeThread); + // geometry background downloads need to happen on the Datagram Processor Thread. The idle loop will + // emit checkBackgroundDownloads to cause the GeometryCache to check it's queue for requested background + // downloads. + QSharedPointer geometryCacheP = DependencyManager::get(); + ResourceCache *geometryCache = geometryCacheP.data(); + connect(this, &Application::checkBackgroundDownloads, geometryCache, &ResourceCache::checkAsynchronousGets); + // connect the DataProcessor processDatagrams slot to the QUDPSocket readyRead() signal connect(&nodeList->getNodeSocket(), &QUdpSocket::readyRead, _datagramProcessor, &DatagramProcessor::processDatagrams); @@ -1556,6 +1564,9 @@ void Application::idle() { idleTimer->start(2); } } + + // check for any requested background downloads. + emit checkBackgroundDownloads(); } void Application::setFullscreen(bool fullscreen) { @@ -3125,7 +3136,7 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) { int viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); - bool eyeRelativeCamera = false; + // bool eyeRelativeCamera = false; if (billboard) { _mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees _mirrorCamera.setPosition(_myAvatar->getPosition() + @@ -3278,6 +3289,14 @@ void Application::clearDomainOctreeDetails() { void Application::domainChanged(const QString& domainHostname) { updateWindowTitle(); clearDomainOctreeDetails(); + _domainConnectionRefusals.clear(); +} + +void Application::domainConnectionDenied(const QString& reason) { + if (!_domainConnectionRefusals.contains(reason)) { + _domainConnectionRefusals.append(reason); + emit domainConnectionRefused(reason); + } } void Application::connectedToDomain(const QString& hostname) { diff --git a/interface/src/Application.h b/interface/src/Application.h index 7764f297d3..84b443b876 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -333,6 +333,9 @@ signals: void svoImportRequested(const QString& url); + void checkBackgroundDownloads(); + void domainConnectionRefused(const QString& reason); + public slots: void domainChanged(const QString& domainHostname); void updateWindowTitle(); @@ -383,6 +386,8 @@ public slots: void setActiveFaceTracker(); + void domainConnectionDenied(const QString& reason); + private slots: void clearDomainOctreeDetails(); void checkFPS(); @@ -607,6 +612,8 @@ private: int _menuBarHeight; QHash _acceptedExtensions; + + QList _domainConnectionRefusals; }; #endif // hifi_Application_h diff --git a/interface/src/DatagramProcessor.cpp b/interface/src/DatagramProcessor.cpp index 475ce406bb..9ac2b51097 100644 --- a/interface/src/DatagramProcessor.cpp +++ b/interface/src/DatagramProcessor.cpp @@ -127,6 +127,7 @@ void DatagramProcessor::processDatagrams() { // and check and signal for an access token so that we can make sure they are logged in qDebug() << "The domain-server denied a connection request: " << reason; qDebug() << "You may need to re-log to generate a keypair so you can provide a username signature."; + application->domainConnectionDenied(reason); AccountManager::getInstance().checkAndSignalForAccessToken(); break; } diff --git a/interface/src/scripting/ControllerScriptingInterface.cpp b/interface/src/scripting/ControllerScriptingInterface.cpp index 35c24346d2..7d6012c880 100644 --- a/interface/src/scripting/ControllerScriptingInterface.cpp +++ b/interface/src/scripting/ControllerScriptingInterface.cpp @@ -353,7 +353,7 @@ void InputController::update() { // TODO for now the InputController is only supporting a JointTracker from a MotionTracker MotionTracker* motionTracker = dynamic_cast< MotionTracker*> (DeviceTracker::getDevice(_deviceTrackerId)); if (motionTracker) { - if (_subTrackerId < motionTracker->numJointTrackers()) { + if ((int)_subTrackerId < motionTracker->numJointTrackers()) { const MotionTracker::JointTracker* joint = motionTracker->getJointTracker(_subTrackerId); if (joint->isActive()) { diff --git a/interface/src/scripting/WindowScriptingInterface.cpp b/interface/src/scripting/WindowScriptingInterface.cpp index 7f4b5ddf45..a5b8128d1e 100644 --- a/interface/src/scripting/WindowScriptingInterface.cpp +++ b/interface/src/scripting/WindowScriptingInterface.cpp @@ -33,6 +33,7 @@ WindowScriptingInterface::WindowScriptingInterface() : const DomainHandler& domainHandler = DependencyManager::get()->getDomainHandler(); connect(&domainHandler, &DomainHandler::hostnameChanged, this, &WindowScriptingInterface::domainChanged); connect(Application::getInstance(), &Application::svoImportRequested, this, &WindowScriptingInterface::svoImportRequested); + connect(Application::getInstance(), &Application::domainConnectionRefused, this, &WindowScriptingInterface::domainConnectionRefused); } WebWindowClass* WindowScriptingInterface::doCreateWebWindow(const QString& title, const QString& url, int width, int height, bool isToolWindow) { diff --git a/interface/src/scripting/WindowScriptingInterface.h b/interface/src/scripting/WindowScriptingInterface.h index 6a812f14e3..9bc8a834bd 100644 --- a/interface/src/scripting/WindowScriptingInterface.h +++ b/interface/src/scripting/WindowScriptingInterface.h @@ -62,6 +62,7 @@ signals: void inlineButtonClicked(const QString& name); void nonBlockingFormClosed(); void svoImportRequested(const QString& url); + void domainConnectionRefused(const QString& reason); private slots: QScriptValue showAlert(const QString& message); diff --git a/interface/src/ui/ApplicationOverlay.cpp b/interface/src/ui/ApplicationOverlay.cpp index d9adaf02e6..633eafc202 100644 --- a/interface/src/ui/ApplicationOverlay.cpp +++ b/interface/src/ui/ApplicationOverlay.cpp @@ -139,6 +139,7 @@ ApplicationOverlay::ApplicationOverlay() : _magnifier(true), _alpha(1.0f), _oculusUIRadius(1.0f), + _trailingAudioLoudness(0.0f), _crosshairTexture(0), _previousBorderWidth(-1), _previousBorderHeight(-1), diff --git a/libraries/audio/src/AudioBuffer.h b/libraries/audio/src/AudioBuffer.h index 4849289743..d2f7c50c91 100644 --- a/libraries/audio/src/AudioBuffer.h +++ b/libraries/audio/src/AudioBuffer.h @@ -88,9 +88,9 @@ template< typename T > void AudioFrameBuffer< T >::deallocateFrames() { if (_frameBuffer) { for (uint32_t i = 0; i < _channelCountMax; ++i) { - delete _frameBuffer[i]; + delete[] _frameBuffer[i]; } - delete _frameBuffer; + delete[] _frameBuffer; } _frameBuffer = NULL; } diff --git a/libraries/audio/src/AudioFilterBank.h b/libraries/audio/src/AudioFilterBank.h index 723fa6b270..7b3b45f56b 100644 --- a/libraries/audio/src/AudioFilterBank.h +++ b/libraries/audio/src/AudioFilterBank.h @@ -88,7 +88,7 @@ public: } void loadProfile(int profileIndex) { - if (profileIndex >= 0 && profileIndex < _profileCount) { + if (profileIndex >= 0 && profileIndex < (int)_profileCount) { for (uint32_t i = 0; i < _filterCount; ++i) { FilterParameter p = _profiles[profileIndex][i]; diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d4eefc0986..eb6706e27f 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -266,6 +266,26 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking); } +void RenderableModelEntityItem::setCollisionModelURL(const QString& url) { + ModelEntityItem::setCollisionModelURL(url); + if (_model) { + _model->setCollisionModelURL(QUrl(url)); + } +} + +bool RenderableModelEntityItem::hasCollisionModel() const { + if (_model) { + return ! _model->getCollisionURL().isEmpty(); + } else { + return !_collisionModelURL.isEmpty(); + } +} + +const QString& RenderableModelEntityItem::getCollisionModelURL() const { + assert (!_model || _collisionModelURL == _model->getCollisionURL().toString()); + return _collisionModelURL; +} + bool RenderableModelEntityItem::isReadyToComputeShape() { if (!_model) { @@ -294,13 +314,67 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) { const QSharedPointer collisionNetworkGeometry = _model->getCollisionGeometry(); const FBXGeometry& fbxGeometry = collisionNetworkGeometry->getFBXGeometry(); + AABox aaBox; _points.clear(); + unsigned int i = 0; foreach (const FBXMesh& mesh, fbxGeometry.meshes) { - _points << mesh.vertices; + + foreach (const FBXMeshPart &meshPart, mesh.parts) { + QVector pointsInPart; + unsigned int triangleCount = meshPart.triangleIndices.size() / 3; + assert((unsigned int)meshPart.triangleIndices.size() == triangleCount*3); + for (unsigned int j = 0; j < triangleCount; j++) { + unsigned int p0Index = meshPart.triangleIndices[j*3]; + unsigned int p1Index = meshPart.triangleIndices[j*3+1]; + unsigned int p2Index = meshPart.triangleIndices[j*3+2]; + + assert(p0Index < (unsigned int)mesh.vertices.size()); + assert(p1Index < (unsigned int)mesh.vertices.size()); + assert(p2Index < (unsigned int)mesh.vertices.size()); + + glm::vec3 p0 = mesh.vertices[p0Index]; + glm::vec3 p1 = mesh.vertices[p1Index]; + glm::vec3 p2 = mesh.vertices[p2Index]; + + aaBox += p0; + aaBox += p1; + aaBox += p2; + + if (!pointsInPart.contains(p0)) { + pointsInPart << p0; + } + if (!pointsInPart.contains(p1)) { + pointsInPart << p1; + } + if (!pointsInPart.contains(p2)) { + pointsInPart << p2; + } + } + + QVector newMeshPoints; + _points << newMeshPoints; + _points[i++] << pointsInPart; + } } - info.setParams(getShapeType(), 0.5f * getDimensions(), _collisionModelURL); - info.setConvexHull(_points); + // make sure we aren't about to divide by zero + glm::vec3 aaBoxDim = aaBox.getDimensions(); + aaBoxDim = glm::clamp(aaBoxDim, glm::vec3(FLT_EPSILON), aaBoxDim); + + glm::vec3 scale = _dimensions / aaBoxDim; + + // multiply each point by scale before handing the point-set off to the physics engine + for (int i = 0; i < _points.size(); i++) { + for (int j = 0; j < _points[i].size(); j++) { + // compensate for registraion + _points[i][j] += _model->getOffset(); + // scale so the collision points match the model points + _points[i][j] *= scale; + } + } + + info.setParams(getShapeType(), _dimensions, _collisionModelURL); + info.setConvexHulls(_points); } } @@ -308,7 +382,9 @@ ShapeType RenderableModelEntityItem::getShapeType() const { // XXX make hull an option in edit.js ? if (!_model || _model->getCollisionURL().isEmpty()) { return _shapeType; - } else { + } else if (_points.size() == 1) { return SHAPE_TYPE_CONVEX_HULL; + } else { + return SHAPE_TYPE_COMPOUND; } } diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index f02dd537fb..9146a04cf8 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -52,6 +52,10 @@ public: bool needsToCallUpdate() const; + virtual void setCollisionModelURL(const QString& url); + virtual bool hasCollisionModel() const; + virtual const QString& getCollisionModelURL() const; + bool isReadyToComputeShape(); void computeShapeInfo(ShapeInfo& info); ShapeType getShapeType() const; @@ -66,7 +70,7 @@ private: QString _currentTextures; QStringList _originalTextures; bool _originalTexturesRead; - QVector _points; + QVector> _points; }; #endif // hifi_RenderableModelEntityItem_h diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index d54e7e6cc1..a73f652282 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -57,7 +57,7 @@ void EntityItem::initFromEntityItemID(const EntityItemID& entityItemID) { _collisionsWillMove = ENTITY_ITEM_DEFAULT_COLLISIONS_WILL_MOVE; _locked = ENTITY_ITEM_DEFAULT_LOCKED; _userData = ENTITY_ITEM_DEFAULT_USER_DATA; - _attribution = ENTITY_ITEM_DEFAULT_ATTRIBUTION; + _marketplaceID = ENTITY_ITEM_DEFAULT_MARKETPLACE_ID; } EntityItem::EntityItem(const EntityItemID& entityItemID) { @@ -117,7 +117,7 @@ EntityPropertyFlags EntityItem::getEntityProperties(EncodeBitstreamParams& param requestedProperties += PROP_COLLISIONS_WILL_MOVE; requestedProperties += PROP_LOCKED; requestedProperties += PROP_USER_DATA; - requestedProperties += PROP_ATTRIBUTION; + requestedProperties += PROP_MARKETPLACE_ID; return requestedProperties; } @@ -240,7 +240,7 @@ OctreeElement::AppendState EntityItem::appendEntityData(OctreePacketData* packet APPEND_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, appendValue, getCollisionsWillMove()); APPEND_ENTITY_PROPERTY(PROP_LOCKED, appendValue, getLocked()); APPEND_ENTITY_PROPERTY(PROP_USER_DATA, appendValue, getUserData()); - APPEND_ENTITY_PROPERTY(PROP_ATTRIBUTION, appendValue, getAttribution()); + APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, getMarketplaceID()); appendSubclassData(packetData, params, entityTreeElementExtraEncodeData, requestedProperties, @@ -555,8 +555,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked); READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA, setUserData); - if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_ATTRIBUTION) { - READ_ENTITY_PROPERTY_STRING(PROP_ATTRIBUTION, setAttribution); + if (args.bitstreamVersion >= VERSION_ENTITIES_HAS_MARKETPLACE_ID) { + READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID); } bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args, propertyFlags, overwriteLocalData); @@ -568,8 +568,8 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef // by doing this parsing here... but it's not likely going to fully recover the content. // // TODO: Remove this conde once we've sufficiently migrated content past this damaged version - if (args.bitstreamVersion == VERSION_ENTITIES_HAS_ATTRIBUTION_DAMAGED) { - READ_ENTITY_PROPERTY_STRING(PROP_ATTRIBUTION, setAttribution); + if (args.bitstreamVersion == VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED) { + READ_ENTITY_PROPERTY_STRING(PROP_MARKETPLACE_ID, setMarketplaceID); } if (overwriteLocalData && (getDirtyFlags() & (EntityItem::DIRTY_POSITION | EntityItem::DIRTY_VELOCITY))) { @@ -838,7 +838,7 @@ EntityItemProperties EntityItem::getProperties() const { COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionsWillMove, getCollisionsWillMove); COPY_ENTITY_PROPERTY_TO_PROPERTIES(locked, getLocked); COPY_ENTITY_PROPERTY_TO_PROPERTIES(userData, getUserData); - COPY_ENTITY_PROPERTY_TO_PROPERTIES(attribution, getAttribution); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(marketplaceID, getMarketplaceID); properties._defaultSettings = false; @@ -867,7 +867,7 @@ bool EntityItem::setProperties(const EntityItemProperties& properties) { 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(attribution, setAttribution); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(marketplaceID, setMarketplaceID); if (somethingChanged) { somethingChangedNotification(); // notify derived classes that something has changed diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 88287f8965..840bc54a2f 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -251,8 +251,8 @@ public: const QString& getUserData() const { return _userData; } void setUserData(const QString& value) { _userData = value; } - const QString& getAttribution() const { return _attribution; } - void setAttribution(const QString& value) { _attribution = value; } + const QString& getMarketplaceID() const { return _marketplaceID; } + void setMarketplaceID(const QString& value) { _marketplaceID = value; } // TODO: get rid of users of getRadius()... float getRadius() const; @@ -342,7 +342,7 @@ protected: bool _collisionsWillMove; bool _locked; QString _userData; - QString _attribution; + QString _marketplaceID; // NOTE: Damping is applied like this: v *= pow(1 - damping, dt) // diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 32352f557d..6e6e897230 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -70,7 +70,7 @@ EntityItemProperties::EntityItemProperties() : CONSTRUCT_PROPERTY(emitStrength, ParticleEffectEntityItem::DEFAULT_EMIT_STRENGTH), CONSTRUCT_PROPERTY(localGravity, ParticleEffectEntityItem::DEFAULT_LOCAL_GRAVITY), CONSTRUCT_PROPERTY(particleRadius, ParticleEffectEntityItem::DEFAULT_PARTICLE_RADIUS), - CONSTRUCT_PROPERTY(attribution, ENTITY_ITEM_DEFAULT_ATTRIBUTION), + CONSTRUCT_PROPERTY(marketplaceID, ENTITY_ITEM_DEFAULT_MARKETPLACE_ID), _id(UNKNOWN_ENTITY_ID), _idSet(false), @@ -260,7 +260,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_EMIT_STRENGTH, emitStrength); CHECK_PROPERTY_CHANGE(PROP_LOCAL_GRAVITY, localGravity); CHECK_PROPERTY_CHANGE(PROP_PARTICLE_RADIUS, particleRadius); - CHECK_PROPERTY_CHANGE(PROP_ATTRIBUTION, attribution); + CHECK_PROPERTY_CHANGE(PROP_MARKETPLACE_ID, marketplaceID); return changedProperties; } @@ -323,7 +323,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons COPY_PROPERTY_TO_QSCRIPTVALUE(emitStrength); COPY_PROPERTY_TO_QSCRIPTVALUE(localGravity); COPY_PROPERTY_TO_QSCRIPTVALUE(particleRadius); - COPY_PROPERTY_TO_QSCRIPTVALUE(attribution); + COPY_PROPERTY_TO_QSCRIPTVALUE(marketplaceID); // Sitting properties support QScriptValue sittingPoints = engine->newObject(); @@ -405,7 +405,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) { COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(emitStrength, setEmitStrength); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(localGravity, setLocalGravity); COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(particleRadius, setParticleRadius); - COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(attribution, setAttribution); + COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(marketplaceID, setMarketplaceID); _lastEdited = usecTimestampNow(); } @@ -591,7 +591,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem APPEND_ENTITY_PROPERTY(PROP_PARTICLE_RADIUS, appendValue, properties.getParticleRadius()); } - APPEND_ENTITY_PROPERTY(PROP_ATTRIBUTION, appendValue, properties.getAttribution()); + APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID()); } if (propertyCount > 0) { int endOfEntityItemData = packetData->getUncompressedByteOffset(); @@ -822,7 +822,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_RADIUS, float, setParticleRadius); } - READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ATTRIBUTION, setAttribution); + READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID); return valid; } @@ -905,7 +905,7 @@ void EntityItemProperties::markAllChanged() { _localGravityChanged = true; _particleRadiusChanged = true; - _attributionChanged = true; + _marketplaceIDChanged = true; } /// The maximum bounding cube for the entity, independent of it's rotation. diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 39e290e602..3f492d649c 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -94,11 +94,11 @@ enum EntityPropertyList { PROP_PARTICLE_RADIUS, PROP_COLLISION_MODEL_URL, - PROP_ATTRIBUTION, + PROP_MARKETPLACE_ID, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties ABOVE this line and then modify PROP_LAST_ITEM below - PROP_LAST_ITEM = PROP_ATTRIBUTION, + PROP_LAST_ITEM = PROP_MARKETPLACE_ID, //////////////////////////////////////////////////////////////////////////////////////////////////// @@ -205,7 +205,7 @@ public: DEFINE_PROPERTY(PROP_EMIT_STRENGTH, EmitStrength, emitStrength, float); DEFINE_PROPERTY(PROP_LOCAL_GRAVITY, LocalGravity, localGravity, float); DEFINE_PROPERTY(PROP_PARTICLE_RADIUS, ParticleRadius, particleRadius, float); - DEFINE_PROPERTY_REF(PROP_ATTRIBUTION, Attribution, attribution, QString); + DEFINE_PROPERTY_REF(PROP_MARKETPLACE_ID, MarketplaceID, marketplaceID, QString); public: float getMaxDimension() const { return glm::max(_dimensions.x, _dimensions.y, _dimensions.z); } @@ -333,7 +333,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) { DEBUG_PROPERTY_IF_CHANGED(debug, properties, EmitStrength, emitStrength, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, LocalGravity, localGravity, ""); DEBUG_PROPERTY_IF_CHANGED(debug, properties, ParticleRadius, particleRadius, ""); - DEBUG_PROPERTY_IF_CHANGED(debug, properties, Attribution, attribution, ""); + DEBUG_PROPERTY_IF_CHANGED(debug, properties, MarketplaceID, marketplaceID, ""); debug << " last edited:" << properties.getLastEdited() << "\n"; debug << " edited ago:" << properties.getEditedAgo() << "\n"; diff --git a/libraries/entities/src/EntityItemPropertiesDefaults.h b/libraries/entities/src/EntityItemPropertiesDefaults.h index e57aea3d85..aa7c77ede4 100644 --- a/libraries/entities/src/EntityItemPropertiesDefaults.h +++ b/libraries/entities/src/EntityItemPropertiesDefaults.h @@ -22,7 +22,7 @@ const glm::vec3 ENTITY_ITEM_ZERO_VEC3(0.0f); const bool ENTITY_ITEM_DEFAULT_LOCKED = false; const QString ENTITY_ITEM_DEFAULT_USER_DATA = QString(""); -const QString ENTITY_ITEM_DEFAULT_ATTRIBUTION = QString(""); +const QString ENTITY_ITEM_DEFAULT_MARKETPLACE_ID = QString(""); const float ENTITY_ITEM_DEFAULT_LOCAL_RENDER_ALPHA = 1.0f; const float ENTITY_ITEM_DEFAULT_GLOW_LEVEL = 0.0f; diff --git a/libraries/entities/src/EntityTree.h b/libraries/entities/src/EntityTree.h index 8536e74e9a..29fecc88b4 100644 --- a/libraries/entities/src/EntityTree.h +++ b/libraries/entities/src/EntityTree.h @@ -95,7 +95,6 @@ public: void deleteEntity(const EntityItemID& entityID, bool force = false, bool ignoreWarnings = false); void deleteEntities(QSet entityIDs, bool force = false, bool ignoreWarnings = false); - void removeEntityFromSimulation(EntityItem* entity); /// \param position point of query in world-frame (meters) /// \param targetRadius radius of query (meters) diff --git a/libraries/entities/src/ModelEntityItem.cpp b/libraries/entities/src/ModelEntityItem.cpp index 181f537daa..55d809e70e 100644 --- a/libraries/entities/src/ModelEntityItem.cpp +++ b/libraries/entities/src/ModelEntityItem.cpp @@ -281,6 +281,13 @@ void ModelEntityItem::updateShapeType(ShapeType type) { } } +void ModelEntityItem::setCollisionModelURL(const QString& url) { + if (_collisionModelURL != url) { + _collisionModelURL = url; + _dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS; + } +} + void ModelEntityItem::setAnimationURL(const QString& url) { _dirtyFlags |= EntityItem::DIRTY_UPDATEABLE; _animationURL = url; diff --git a/libraries/entities/src/ModelEntityItem.h b/libraries/entities/src/ModelEntityItem.h index 081cb429ed..9e34de445b 100644 --- a/libraries/entities/src/ModelEntityItem.h +++ b/libraries/entities/src/ModelEntityItem.h @@ -57,13 +57,13 @@ public: const rgbColor& getColor() const { return _color; } xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; } bool hasModel() const { return !_modelURL.isEmpty(); } - bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); } + virtual bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); } static const QString DEFAULT_MODEL_URL; const QString& getModelURL() const { return _modelURL; } static const QString DEFAULT_COLLISION_MODEL_URL; - const QString& getCollisionModelURL() const { return _collisionModelURL; } + virtual const QString& getCollisionModelURL() const { return _collisionModelURL; } bool hasAnimation() const { return !_animationURL.isEmpty(); } static const QString DEFAULT_ANIMATION_URL; @@ -78,7 +78,7 @@ public: // model related properties void setModelURL(const QString& url) { _modelURL = url; } - void setCollisionModelURL(const QString& url) { _collisionModelURL = url; } + virtual void setCollisionModelURL(const QString& url); void setAnimationURL(const QString& url); static const float DEFAULT_ANIMATION_FRAME_INDEX; void setAnimationFrameIndex(float value); diff --git a/libraries/fbx/src/OBJReader.cpp b/libraries/fbx/src/OBJReader.cpp index 0aaf8772a2..db2733f27b 100644 --- a/libraries/fbx/src/OBJReader.cpp +++ b/libraries/fbx/src/OBJReader.cpp @@ -249,7 +249,20 @@ bool parseOBJGroup(OBJTokenizer &tokenizer, const QVariantHash& mapping, } else if (indices.count() == 4) { meshPart.quadIndices << indices; } else { - qDebug() << "no support for more than 4 vertices on a face in OBJ files"; + // some obj writers (maya) will write a face with lots of points. + for (int i = 1; i < indices.count() - 1; i++) { + // break the face into triangles + meshPart.triangleIndices.append(indices[0]); + meshPart.triangleIndices.append(indices[i]); + meshPart.triangleIndices.append(indices[i+1]); + } + if (indices.count() == normalIndices.count()) { + for (int i = 1; i < normalIndices.count() - 1; i++) { + faceNormalIndexes.append(normalIndices[0]); + faceNormalIndexes.append(normalIndices[i]); + faceNormalIndexes.append(normalIndices[i+1]); + } + } } } else { // something we don't (yet) care about diff --git a/libraries/networking/src/PacketHeaders.cpp b/libraries/networking/src/PacketHeaders.cpp index abac09d238..78a27af686 100644 --- a/libraries/networking/src/PacketHeaders.cpp +++ b/libraries/networking/src/PacketHeaders.cpp @@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) { return 1; case PacketTypeEntityAddOrEdit: case PacketTypeEntityData: - return VERSION_ENTITIES_HAS_ATTRIBUTION; + return VERSION_ENTITIES_HAS_MARKETPLACE_ID; case PacketTypeEntityErase: return 2; case PacketTypeAudioStreamStats: diff --git a/libraries/networking/src/PacketHeaders.h b/libraries/networking/src/PacketHeaders.h index 5822f2af3a..924d219b75 100644 --- a/libraries/networking/src/PacketHeaders.h +++ b/libraries/networking/src/PacketHeaders.h @@ -132,8 +132,8 @@ const PacketVersion VERSION_ENTITIES_LIGHT_HAS_INTENSITY_AND_COLOR_PROPERTIES = const PacketVersion VERSION_ENTITIES_HAS_PARTICLES = 10; const PacketVersion VERSION_ENTITIES_USE_METERS_AND_RADIANS = 11; const PacketVersion VERSION_ENTITIES_HAS_COLLISION_MODEL = 12; -const PacketVersion VERSION_ENTITIES_HAS_ATTRIBUTION_DAMAGED = 13; -const PacketVersion VERSION_ENTITIES_HAS_ATTRIBUTION = 14; +const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID_DAMAGED = 13; +const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14; const PacketVersion VERSION_OCTREE_HAS_FILE_BREAKS = 1; #endif // hifi_PacketHeaders_h diff --git a/libraries/networking/src/ResourceCache.cpp b/libraries/networking/src/ResourceCache.cpp index b574eb1aeb..739e587f5f 100644 --- a/libraries/networking/src/ResourceCache.cpp +++ b/libraries/networking/src/ResourceCache.cpp @@ -18,6 +18,7 @@ #include #include +#include #include "NetworkAccessManager.h" #include "ResourceCache.h" @@ -48,32 +49,40 @@ void ResourceCache::refresh(const QUrl& url) { } } +void ResourceCache::getResourceAsynchronously(const QUrl& url) { + qDebug() << "ResourceCache::getResourceAsynchronously" << url.toString(); + _resourcesToBeGottenLock.lockForWrite(); + _resourcesToBeGotten.enqueue(QUrl(url)); + _resourcesToBeGottenLock.unlock(); +} + +void ResourceCache::checkAsynchronousGets() { + assert(QThread::currentThread() == thread()); + if (!_resourcesToBeGotten.isEmpty()) { + _resourcesToBeGottenLock.lockForWrite(); + QUrl url = _resourcesToBeGotten.dequeue(); + _resourcesToBeGottenLock.unlock(); + getResource(url); + } +} + QSharedPointer ResourceCache::getResource(const QUrl& url, const QUrl& fallback, - bool delayLoad, void* extra, bool block) { + bool delayLoad, void* extra) { + QSharedPointer resource = _resources.value(url); + if (!resource.isNull()) { + return resource; + } + if (QThread::currentThread() != thread()) { - // This will re-call this method in the main thread. If block is true and the main thread - // is waiting on a lock, we'll deadlock here. - if (block) { - QSharedPointer result; - QMetaObject::invokeMethod(this, "getResource", Qt::BlockingQueuedConnection, - Q_RETURN_ARG(QSharedPointer, result), Q_ARG(const QUrl&, url), - Q_ARG(const QUrl&, fallback), Q_ARG(bool, delayLoad), Q_ARG(void*, extra)); - return result; - } else { - // Queue the re-invocation of this method, but if the main thread is blocked, don't wait. The - // return value may be NULL -- it's expected that this will be called again later, in order - // to receive the actual Resource. - QMetaObject::invokeMethod(this, "getResource", Qt::QueuedConnection, - Q_ARG(const QUrl&, url), - Q_ARG(const QUrl&, fallback), Q_ARG(bool, delayLoad), Q_ARG(void*, extra)); - return _resources.value(url); - } + assert(delayLoad); + getResourceAsynchronously(url); + return QSharedPointer(); } if (!url.isValid() && !url.isEmpty() && fallback.isValid()) { return getResource(fallback, QUrl(), delayLoad); } - QSharedPointer resource = _resources.value(url); + if (resource.isNull()) { resource = createResource(url, fallback.isValid() ? getResource(fallback, QUrl(), true) : QSharedPointer(), delayLoad, extra); diff --git a/libraries/networking/src/ResourceCache.h b/libraries/networking/src/ResourceCache.h index d4aa9a7fd9..c7aceb2e1a 100644 --- a/libraries/networking/src/ResourceCache.h +++ b/libraries/networking/src/ResourceCache.h @@ -21,6 +21,8 @@ #include #include #include +#include +#include #include @@ -79,6 +81,9 @@ public: void refresh(const QUrl& url); +public slots: + void checkAsynchronousGets(); + protected: qint64 _unusedResourcesMaxSize = DEFAULT_UNUSED_MAX_SIZE; qint64 _unusedResourcesSize = 0; @@ -89,7 +94,7 @@ protected: /// \param delayLoad if true, don't load the resource immediately; wait until load is first requested /// \param extra extra data to pass to the creator, if appropriate Q_INVOKABLE QSharedPointer getResource(const QUrl& url, const QUrl& fallback = QUrl(), - bool delayLoad = false, void* extra = NULL, bool block = true); + bool delayLoad = false, void* extra = NULL); /// Creates a new resource. virtual QSharedPointer createResource(const QUrl& url, @@ -109,6 +114,11 @@ private: int _lastLRUKey = 0; static int _requestLimit; + + void getResourceAsynchronously(const QUrl& url); + QReadWriteLock _resourcesToBeGottenLock; + QQueue _resourcesToBeGotten; + }; /// Base class for resources. diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 09c6b5599f..148746a76e 100644 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -235,7 +235,9 @@ CharacterController::CharacterController(AvatarData* avatarData) { _jumpToHoverStart = 0; setMaxSlope(btRadians(45.0f)); _lastStepUp = 0.0f; - _pendingFlags = 0; + + _pendingFlags = PENDING_FLAG_UPDATE_SHAPE; + updateShapeIfNecessary(); } CharacterController::~CharacterController() { @@ -786,14 +788,17 @@ void CharacterController::setEnabled(bool enabled) { void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { if (_dynamicsWorld != world) { - if (_dynamicsWorld) { - _dynamicsWorld->removeCollisionObject(getGhostObject()); - _dynamicsWorld->removeAction(this); + if (_dynamicsWorld) { + if (_ghostObject) { + _dynamicsWorld->removeCollisionObject(_ghostObject); + _dynamicsWorld->removeAction(this); + } + _dynamicsWorld = NULL; } - _dynamicsWorld = world; - if (_dynamicsWorld) { + if (world && _ghostObject) { + _dynamicsWorld = world; _pendingFlags &= ~ PENDING_FLAG_JUMP; - _dynamicsWorld->addCollisionObject(getGhostObject(), + _dynamicsWorld->addCollisionObject(_ghostObject, btBroadphaseProxy::CharacterFilter, btBroadphaseProxy::StaticFilter | btBroadphaseProxy::DefaultFilter); _dynamicsWorld->addAction(this); @@ -876,7 +881,7 @@ void CharacterController::preSimulation(btScalar timeStep) { } void CharacterController::postSimulation() { - if (_enabled) { + if (_enabled && _ghostObject) { const btTransform& avatarTransform = _ghostObject->getWorldTransform(); glm::quat rotation = bulletToGLM(avatarTransform.getRotation()); glm::vec3 position = bulletToGLM(avatarTransform.getOrigin()); diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index cd0769255b..35eb006655 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -169,7 +169,9 @@ void EntityMotionState::updateObjectVelocities() { } void EntityMotionState::computeShapeInfo(ShapeInfo& shapeInfo) { - _entity->computeShapeInfo(shapeInfo); + if (_entity->isReadyToComputeShape()) { + _entity->computeShapeInfo(shapeInfo); + } } float EntityMotionState::computeMass(const ShapeInfo& shapeInfo) const { diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 9ca718e19a..f7dc90e72f 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -29,6 +29,12 @@ PhysicsEngine::PhysicsEngine(const glm::vec3& offset) PhysicsEngine::~PhysicsEngine() { // TODO: delete engine components... if we ever plan to create more than one instance + delete _collisionConfig; + delete _collisionDispatcher; + delete _broadphaseFilter; + delete _constraintSolver; + delete _dynamicsWorld; + // delete _ghostPairCallback; } // begin EntitySimulation overrides diff --git a/libraries/physics/src/ShapeInfoUtil.cpp b/libraries/physics/src/ShapeInfoUtil.cpp index 116be984b9..8900c5a0dc 100644 --- a/libraries/physics/src/ShapeInfoUtil.cpp +++ b/libraries/physics/src/ShapeInfoUtil.cpp @@ -29,6 +29,9 @@ int ShapeInfoUtil::toBulletShapeType(int shapeInfoType) { case SHAPE_TYPE_CONVEX_HULL: bulletShapeType = CONVEX_HULL_SHAPE_PROXYTYPE; break; + case SHAPE_TYPE_COMPOUND: + bulletShapeType = COMPOUND_SHAPE_PROXYTYPE; + break; } return bulletShapeType; } @@ -48,6 +51,9 @@ int ShapeInfoUtil::fromBulletShapeType(int bulletShapeType) { case CONVEX_HULL_SHAPE_PROXYTYPE: shapeInfoType = SHAPE_TYPE_CONVEX_HULL; break; + case COMPOUND_SHAPE_PROXYTYPE: + shapeInfoType = SHAPE_TYPE_COMPOUND; + break; } return shapeInfoType; } @@ -70,12 +76,34 @@ void ShapeInfoUtil::collectInfoFromShape(const btCollisionShape* shape, ShapeInf const btConvexHullShape* convexHullShape = static_cast(shape); const int numPoints = convexHullShape->getNumPoints(); const btVector3* btPoints = convexHullShape->getUnscaledPoints(); - QVector points; + QVector> points; + QVector childPoints; for (int i = 0; i < numPoints; i++) { glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ()); - points << point; + childPoints << point; } - info.setConvexHull(points); + points << childPoints; + info.setConvexHulls(points); + } + break; + case SHAPE_TYPE_COMPOUND: { + const btCompoundShape* compoundShape = static_cast(shape); + const int numChildShapes = compoundShape->getNumChildShapes(); + QVector> points; + for (int i = 0; i < numChildShapes; i ++) { + const btCollisionShape* childShape = compoundShape->getChildShape(i); + const btConvexHullShape* convexHullShape = static_cast(childShape); + const int numPoints = convexHullShape->getNumPoints(); + const btVector3* btPoints = convexHullShape->getUnscaledPoints(); + + QVector childPoints; + for (int j = 0; j < numPoints; j++) { + glm::vec3 point(btPoints->getX(), btPoints->getY(), btPoints->getZ()); + childPoints << point; + } + points << childPoints; + } + info.setConvexHulls(points); } break; default: { @@ -108,12 +136,32 @@ btCollisionShape* ShapeInfoUtil::createShapeFromInfo(const ShapeInfo& info) { } break; case SHAPE_TYPE_CONVEX_HULL: { - shape = new btConvexHullShape(); - const QVector& points = info.getPoints(); - foreach (glm::vec3 point, points) { + auto hull = new btConvexHullShape(); + const QVector>& points = info.getPoints(); + foreach (glm::vec3 point, points[0]) { btVector3 btPoint(point[0], point[1], point[2]); - static_cast(shape)->addPoint(btPoint); + hull->addPoint(btPoint, false); } + hull->recalcLocalAabb(); + shape = hull; + } + break; + case SHAPE_TYPE_COMPOUND: { + auto compound = new btCompoundShape(); + const QVector>& points = info.getPoints(); + + btTransform trans; + trans.setIdentity(); + foreach (QVector hullPoints, points) { + auto hull = new btConvexHullShape(); + foreach (glm::vec3 point, hullPoints) { + btVector3 btPoint(point[0], point[1], point[2]); + hull->addPoint(btPoint, false); + } + hull->recalcLocalAabb(); + compound->addChildShape (trans, hull); + } + shape = compound; } break; } diff --git a/libraries/physics/src/ShapeInfoUtil.h b/libraries/physics/src/ShapeInfoUtil.h index fb59f30c69..9585161440 100644 --- a/libraries/physics/src/ShapeInfoUtil.h +++ b/libraries/physics/src/ShapeInfoUtil.h @@ -20,6 +20,8 @@ // translates between ShapeInfo and btShape namespace ShapeInfoUtil { + + // XXX is collectInfoFromShape no longer strictly needed? void collectInfoFromShape(const btCollisionShape* shape, ShapeInfo& info); btCollisionShape* createShapeFromInfo(const ShapeInfo& info); diff --git a/libraries/physics/src/ShapeManager.cpp b/libraries/physics/src/ShapeManager.cpp index 513fbfa7a5..b4d322a4a3 100644 --- a/libraries/physics/src/ShapeManager.cpp +++ b/libraries/physics/src/ShapeManager.cpp @@ -9,6 +9,8 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include + #include #include "ShapeInfoUtil.h" @@ -35,6 +37,7 @@ btCollisionShape* ShapeManager::getShape(const ShapeInfo& info) { const float MIN_SHAPE_DIAGONAL_SQUARED = 3.0e-4f; // 1 cm cube const float MAX_SHAPE_DIAGONAL_SQUARED = 3.0e4f; // 100 m cube if (diagonal < MIN_SHAPE_DIAGONAL_SQUARED || diagonal > MAX_SHAPE_DIAGONAL_SQUARED) { + // qDebug() << "ShapeManager::getShape -- not making shape due to size" << diagonal; return NULL; } DoubleHashKey key = info.getHash(); @@ -100,6 +103,18 @@ void ShapeManager::collectGarbage() { DoubleHashKey& key = _pendingGarbage[i]; ShapeReference* shapeRef = _shapeMap.find(key); if (shapeRef && shapeRef->refCount == 0) { + // if the shape we're about to delete is compound, delete the children first. + auto shapeType = ShapeInfoUtil::fromBulletShapeType(shapeRef->shape->getShapeType()); + if (shapeType == SHAPE_TYPE_COMPOUND) { + const btCompoundShape* compoundShape = static_cast(shapeRef->shape); + const int numChildShapes = compoundShape->getNumChildShapes(); + QVector> points; + for (int i = 0; i < numChildShapes; i ++) { + const btCollisionShape* childShape = compoundShape->getChildShape(i); + delete childShape; + } + } + delete shapeRef->shape; _shapeMap.remove(key); } diff --git a/libraries/render-utils/src/DeferredLightingEffect.cpp b/libraries/render-utils/src/DeferredLightingEffect.cpp index 13bf947d71..ffa84adbdf 100644 --- a/libraries/render-utils/src/DeferredLightingEffect.cpp +++ b/libraries/render-utils/src/DeferredLightingEffect.cpp @@ -134,7 +134,7 @@ void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radi void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color, float intensity, const glm::quat& orientation, float exponent, float cutoff) { - int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size(); + unsigned int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size(); if (lightID >= _allocatedLights.size()) { _allocatedLights.push_back(model::LightPointer(new model::Light())); } diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index e60409e36f..f8fc4633cc 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -1771,8 +1771,8 @@ void GeometryCache::renderLine(const glm::vec2& p1, const glm::vec2& p2, } -QSharedPointer GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad, bool block) { - return getResource(url, fallback, delayLoad, NULL, block).staticCast(); +QSharedPointer GeometryCache::getGeometry(const QUrl& url, const QUrl& fallback, bool delayLoad) { + return getResource(url, fallback, delayLoad, NULL).staticCast(); } QSharedPointer GeometryCache::createResource(const QUrl& url, diff --git a/libraries/render-utils/src/GeometryCache.h b/libraries/render-utils/src/GeometryCache.h index a64d041fc1..37156a6c71 100644 --- a/libraries/render-utils/src/GeometryCache.h +++ b/libraries/render-utils/src/GeometryCache.h @@ -203,8 +203,7 @@ public: /// Loads geometry from the specified URL. /// \param fallback a fallback URL to load if the desired one is unavailable /// \param delayLoad if true, don't load the geometry immediately; wait until load is first requested - QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), - bool delayLoad = false, bool block = true); + QSharedPointer getGeometry(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); protected: diff --git a/libraries/render-utils/src/Model.cpp b/libraries/render-utils/src/Model.cpp index 873f458ccf..81c9f9448c 100644 --- a/libraries/render-utils/src/Model.cpp +++ b/libraries/render-utils/src/Model.cpp @@ -325,6 +325,8 @@ void Model::init() { _skinTranslucentProgram = gpu::ShaderPointer(gpu::Shader::createProgram(skinModelVertex, modelTranslucentPixel)); makeResult = gpu::Shader::makeProgram(*_skinTranslucentProgram, slotBindings); initSkinProgram(_skinTranslucentProgram, _skinTranslucentLocations); + + (void) makeResult; // quiet compiler } } @@ -1032,12 +1034,22 @@ void Model::setURL(const QUrl& url, const QUrl& fallback, bool retainCurrent, bo } } -void Model::setCollisionModelURL(const QUrl& url, const QUrl& fallback, bool delayLoad) { + +const QSharedPointer Model::getCollisionGeometry(bool delayLoad) +{ + if (_collisionGeometry.isNull() && !_collisionUrl.isEmpty()) { + _collisionGeometry = DependencyManager::get()->getGeometry(_collisionUrl, QUrl(), delayLoad); + } + + return _collisionGeometry; +} + +void Model::setCollisionModelURL(const QUrl& url) { if (_collisionUrl == url) { return; } _collisionUrl = url; - _collisionGeometry = DependencyManager::get()->getGeometry(url, fallback, delayLoad); + _collisionGeometry = DependencyManager::get()->getGeometry(url, QUrl(), true); } bool Model::getJointPositionInWorldFrame(int jointIndex, glm::vec3& position) const { diff --git a/libraries/render-utils/src/Model.h b/libraries/render-utils/src/Model.h index 05db20b056..3b4cbdd450 100644 --- a/libraries/render-utils/src/Model.h +++ b/libraries/render-utils/src/Model.h @@ -109,7 +109,7 @@ public: const QUrl& getURL() const { return _url; } // Set the model to use for collisions - Q_INVOKABLE void setCollisionModelURL(const QUrl& url, const QUrl& fallback = QUrl(), bool delayLoad = false); + Q_INVOKABLE void setCollisionModelURL(const QUrl& url); const QUrl& getCollisionURL() const { return _collisionUrl; } /// Sets the distance parameter used for LOD computations. @@ -134,7 +134,7 @@ public: const QSharedPointer& getGeometry() const { return _geometry; } /// Returns a reference to the shared collision geometry. - const QSharedPointer getCollisionGeometry() {return _collisionGeometry; } + const QSharedPointer getCollisionGeometry(bool delayLoad = true); /// Returns the number of joint states in the model. int getJointStateCount() const { return _jointStates.size(); } diff --git a/libraries/shared/src/ShapeInfo.cpp b/libraries/shared/src/ShapeInfo.cpp index 61432830e7..5fe1fc230d 100644 --- a/libraries/shared/src/ShapeInfo.cpp +++ b/libraries/shared/src/ShapeInfo.cpp @@ -23,6 +23,7 @@ void ShapeInfo::clear() { void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString url) { _type = type; + _points.clear(); switch(type) { case SHAPE_TYPE_NONE: _halfExtents = glm::vec3(0.0f); @@ -37,6 +38,12 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString break; } case SHAPE_TYPE_CONVEX_HULL: + _url = QUrl(url); + // halfExtents aren't used by convex-hull or compound convex-hull except as part of + // the generation of the key for the ShapeManager. + _halfExtents = halfExtents; + break; + case SHAPE_TYPE_COMPOUND: _url = QUrl(url); _halfExtents = halfExtents; break; @@ -47,31 +54,44 @@ void ShapeInfo::setParams(ShapeType type, const glm::vec3& halfExtents, QString } void ShapeInfo::setBox(const glm::vec3& halfExtents) { + _url = ""; _type = SHAPE_TYPE_BOX; _halfExtents = halfExtents; + _points.clear(); _doubleHashKey.clear(); } void ShapeInfo::setSphere(float radius) { + _url = ""; _type = SHAPE_TYPE_SPHERE; _halfExtents = glm::vec3(radius, radius, radius); + _points.clear(); _doubleHashKey.clear(); } void ShapeInfo::setEllipsoid(const glm::vec3& halfExtents) { + _url = ""; _type = SHAPE_TYPE_ELLIPSOID; _halfExtents = halfExtents; + _points.clear(); _doubleHashKey.clear(); } -void ShapeInfo::setConvexHull(const QVector& points) { - _type = SHAPE_TYPE_CONVEX_HULL; +void ShapeInfo::setConvexHulls(const QVector>& points) { + if (points.size() == 1) { + _type = SHAPE_TYPE_CONVEX_HULL; + } else { + _type = SHAPE_TYPE_COMPOUND; + } _points = points; + _doubleHashKey.clear(); } void ShapeInfo::setCapsuleY(float radius, float halfHeight) { + _url = ""; _type = SHAPE_TYPE_CAPSULE_Y; _halfExtents = glm::vec3(radius, halfHeight, radius); + _points.clear(); _doubleHashKey.clear(); } diff --git a/libraries/shared/src/ShapeInfo.h b/libraries/shared/src/ShapeInfo.h index 0a55f7c51d..4dce121d64 100644 --- a/libraries/shared/src/ShapeInfo.h +++ b/libraries/shared/src/ShapeInfo.h @@ -44,14 +44,14 @@ public: void setBox(const glm::vec3& halfExtents); void setSphere(float radius); void setEllipsoid(const glm::vec3& halfExtents); - void setConvexHull(const QVector& points); + void setConvexHulls(const QVector>& points); void setCapsuleY(float radius, float halfHeight); const int getType() const { return _type; } const glm::vec3& getHalfExtents() const { return _halfExtents; } - const QVector& getPoints() const { return _points; } + const QVector>& getPoints() const { return _points; } void clearPoints () { _points.clear(); } void appendToPoints (const QVector& newPoints) { _points << newPoints; } @@ -64,8 +64,8 @@ protected: ShapeType _type = SHAPE_TYPE_NONE; glm::vec3 _halfExtents = glm::vec3(0.0f); DoubleHashKey _doubleHashKey; - QVector _points; // points for convex collision hull - QUrl _url; // url for model of convex collision hull + QVector> _points; // points for convex collision hulls + QUrl _url; // url for model of convex collision hulls }; #endif // hifi_ShapeInfo_h diff --git a/libraries/shared/src/SimpleMovingAverage.cpp b/libraries/shared/src/SimpleMovingAverage.cpp index 64198d2a06..90a9509c91 100644 --- a/libraries/shared/src/SimpleMovingAverage.cpp +++ b/libraries/shared/src/SimpleMovingAverage.cpp @@ -14,6 +14,7 @@ SimpleMovingAverage::SimpleMovingAverage(int numSamplesToAverage) : _numSamples(0), + _lastEventTimestamp(0), _average(0.0f), _eventDeltaAverage(0.0f), WEIGHTING(1.0f / numSamplesToAverage), diff --git a/tools/CMakeLists.txt b/tools/CMakeLists.txt index 5c7c306a62..ba2938aaa6 100644 --- a/tools/CMakeLists.txt +++ b/tools/CMakeLists.txt @@ -8,5 +8,5 @@ set_target_properties(scribe PROPERTIES FOLDER "Tools") find_package(VHACD) if(VHACD_FOUND) add_subdirectory(vhacd) -set_target_properties(vhacd PROPERTIES FOLDER "Tools") +# set_target_properties(vhacd PROPERTIES FOLDER "Tools") endif() diff --git a/tools/refresh-tags.sh b/tools/refresh-tags.sh index d3157fa179..e8040dac81 100755 --- a/tools/refresh-tags.sh +++ b/tools/refresh-tags.sh @@ -2,13 +2,13 @@ rm -f TAGS -find . -name *.h -print | while read I +find . -name *.h -print | grep -v build-ext |while read I do etags --append "$I" done -find . -name *.cpp -print | grep -v 'moc_' | while read I +find . -name *.cpp -print | grep -v 'moc_' | grep -v build-ext | while read I do etags --append "$I" done