From c4236d7442fc9e97b466aa20a03abf86577e4ce3 Mon Sep 17 00:00:00 2001 From: David Back Date: Tue, 10 Jul 2018 13:53:18 -0700 Subject: [PATCH 01/20] allow rendering empty web entity --- .../entities-renderer/src/RenderableWebEntityItem.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp index 17d6d58781..5e30b1da0b 100644 --- a/libraries/entities-renderer/src/RenderableWebEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableWebEntityItem.cpp @@ -178,10 +178,6 @@ void WebEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene withWriteLock([&] { - if (_contentType == ContentType::NoContent) { - return; - } - // This work must be done on the main thread // If we couldn't create a new web surface, exit if (!hasWebSurface() && !buildWebSurface(entity)) { @@ -315,7 +311,13 @@ bool WebEntityRenderer::buildWebSurface(const TypedEntityPointer& entity) { }); } else if (_contentType == ContentType::QmlContent) { _webSurface->load(_lastSourceUrl); + } else if (_contentType == ContentType::NoContent) { + // Show empty white panel + _webSurface->load("controls/WebEntityView.qml", [this](QQmlContext* context, QObject* item) { + item->setProperty(URL_PROPERTY, ""); + }); } + _fadeStartTime = usecTimestampNow(); _webSurface->resume(); From 207aea871277ab60d90b130e7bac0f20cb17b9b7 Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Mon, 16 Jul 2018 10:29:34 -0700 Subject: [PATCH 02/20] remove cruft from rendering collision shapes --- .../src/RenderableModelEntityItem.cpp | 12 - .../src/RenderableModelEntityItem.h | 8 - libraries/entities/src/EntityItem.h | 2 - .../physics/src/CollisionRenderMeshCache.cpp | 217 -------------- .../physics/src/CollisionRenderMeshCache.h | 48 --- libraries/physics/src/EntityMotionState.cpp | 7 - libraries/physics/src/EntityMotionState.h | 1 - .../src/CollisionRenderMeshCacheTests.cpp | 277 ------------------ .../src/CollisionRenderMeshCacheTests.h | 26 -- 9 files changed, 598 deletions(-) delete mode 100644 libraries/physics/src/CollisionRenderMeshCache.cpp delete mode 100644 libraries/physics/src/CollisionRenderMeshCache.h delete mode 100644 tests/physics/src/CollisionRenderMeshCacheTests.cpp delete mode 100644 tests/physics/src/CollisionRenderMeshCacheTests.h diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp index d8ac3dc63e..3f3c751943 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.cpp @@ -699,14 +699,6 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& shapeInfo) { adjustShapeInfoByRegistration(shapeInfo); } -void RenderableModelEntityItem::setCollisionShape(const btCollisionShape* shape) { - const void* key = static_cast(shape); - if (_collisionMeshKey != key) { - _collisionMeshKey = key; - emit requestCollisionGeometryUpdate(); - } -} - void RenderableModelEntityItem::setJointMap(std::vector jointMap) { if (jointMap.size() > 0) { _jointMap = jointMap; @@ -1278,10 +1270,6 @@ bool ModelEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPoin return false; } -void ModelEntityRenderer::setCollisionMeshKey(const void*key) { - _collisionMeshKey = key; -} - void ModelEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) { DETAILED_PROFILE_RANGE(simulation_physics, __FUNCTION__); if (_hasModel != entity->hasModel()) { diff --git a/libraries/entities-renderer/src/RenderableModelEntityItem.h b/libraries/entities-renderer/src/RenderableModelEntityItem.h index 91e5496b97..7a6c882c5a 100644 --- a/libraries/entities-renderer/src/RenderableModelEntityItem.h +++ b/libraries/entities-renderer/src/RenderableModelEntityItem.h @@ -78,8 +78,6 @@ public: virtual bool isReadyToComputeShape() const override; virtual void computeShapeInfo(ShapeInfo& shapeInfo) override; - void setCollisionShape(const btCollisionShape* shape) override; - virtual bool contains(const glm::vec3& point) const override; void stopModelOverrideIfNoParent(); @@ -112,10 +110,6 @@ public: virtual QStringList getJointNames() const override; bool getMeshes(MeshProxyList& result) override; // deprecated - const void* getCollisionMeshKey() const { return _collisionMeshKey; } - -signals: - void requestCollisionGeometryUpdate(); private: bool needsUpdateModelBounds() const; @@ -130,7 +124,6 @@ private: QVariantMap _originalTextures; bool _dimensionsInitialized { true }; bool _needsJointSimulation { false }; - const void* _collisionMeshKey { nullptr }; }; namespace render { namespace entities { @@ -161,7 +154,6 @@ protected: virtual bool needsRenderUpdate() const override; virtual void doRender(RenderArgs* args) override; virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) override; - void setCollisionMeshKey(const void* key); render::hifi::Tag getTagMask() const override; diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 3a11fd821a..81cb18dee4 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -378,8 +378,6 @@ public: /// return preferred shape type (actual physical shape may differ) virtual ShapeType getShapeType() const { return SHAPE_TYPE_NONE; } - virtual void setCollisionShape(const btCollisionShape* shape) {} - void setPosition(const glm::vec3& value); virtual void setParentID(const QUuid& parentID) override; virtual void setShapeType(ShapeType type) { /* do nothing */ } diff --git a/libraries/physics/src/CollisionRenderMeshCache.cpp b/libraries/physics/src/CollisionRenderMeshCache.cpp deleted file mode 100644 index 6f66b9af10..0000000000 --- a/libraries/physics/src/CollisionRenderMeshCache.cpp +++ /dev/null @@ -1,217 +0,0 @@ -// -// CollisionRenderMeshCache.cpp -// libraries/physics/src -// -// Created by Andrew Meadows 2016.07.13 -// Copyright 2016 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 -// - -#include "CollisionRenderMeshCache.h" - -#include - -#include -#include - -#include // for MAX_HULL_POINTS - -const int32_t MAX_HULL_INDICES = 6 * MAX_HULL_POINTS; -const int32_t MAX_HULL_NORMALS = MAX_HULL_INDICES; -float tempVertices[MAX_HULL_NORMALS]; -graphics::Index tempIndexBuffer[MAX_HULL_INDICES]; - -bool copyShapeToMesh(const btTransform& transform, const btConvexShape* shape, - gpu::BufferView& vertices, gpu::BufferView& indices, gpu::BufferView& parts, - gpu::BufferView& normals) { - assert(shape); - - btShapeHull hull(shape); - if (!hull.buildHull(shape->getMargin())) { - return false; - } - - int32_t numHullIndices = hull.numIndices(); - assert(numHullIndices <= MAX_HULL_INDICES); - - int32_t numHullVertices = hull.numVertices(); - assert(numHullVertices <= MAX_HULL_POINTS); - - { // new part - graphics::Mesh::Part part; - part._startIndex = (graphics::Index)indices.getNumElements(); - part._numIndices = (graphics::Index)numHullIndices; - // FIXME: the render code cannot handle the case where part._baseVertex != 0 - //part._baseVertex = vertices.getNumElements(); // DOES NOT WORK - part._baseVertex = 0; - - gpu::BufferView::Size numBytes = sizeof(graphics::Mesh::Part); - const gpu::Byte* data = reinterpret_cast(&part); - parts._buffer->append(numBytes, data); - parts._size = parts._buffer->getSize(); - } - - const int32_t SIZE_OF_VEC3 = 3 * sizeof(float); - graphics::Index indexOffset = (graphics::Index)vertices.getNumElements(); - - { // new indices - const uint32_t* hullIndices = hull.getIndexPointer(); - // FIXME: the render code cannot handle the case where part._baseVertex != 0 - // so we must add an offset to each index - for (int32_t i = 0; i < numHullIndices; ++i) { - tempIndexBuffer[i] = hullIndices[i] + indexOffset; - } - const gpu::Byte* data = reinterpret_cast(tempIndexBuffer); - gpu::BufferView::Size numBytes = (gpu::BufferView::Size)(sizeof(graphics::Index) * numHullIndices); - indices._buffer->append(numBytes, data); - indices._size = indices._buffer->getSize(); - } - { // new vertices - const btVector3* hullVertices = hull.getVertexPointer(); - assert(numHullVertices <= MAX_HULL_POINTS); - for (int32_t i = 0; i < numHullVertices; ++i) { - btVector3 transformedPoint = transform * hullVertices[i]; - memcpy(tempVertices + 3 * i, transformedPoint.m_floats, SIZE_OF_VEC3); - } - gpu::BufferView::Size numBytes = sizeof(float) * (3 * numHullVertices); - const gpu::Byte* data = reinterpret_cast(tempVertices); - vertices._buffer->append(numBytes, data); - vertices._size = vertices._buffer->getSize(); - } - { // new normals - // compute average point - btVector3 avgVertex(0.0f, 0.0f, 0.0f); - const btVector3* hullVertices = hull.getVertexPointer(); - for (int i = 0; i < numHullVertices; ++i) { - avgVertex += hullVertices[i]; - } - avgVertex = transform * (avgVertex * (1.0f / (float)numHullVertices)); - - for (int i = 0; i < numHullVertices; ++i) { - btVector3 norm = transform * hullVertices[i] - avgVertex; - btScalar normLength = norm.length(); - if (normLength > FLT_EPSILON) { - norm /= normLength; - } - memcpy(tempVertices + 3 * i, norm.m_floats, SIZE_OF_VEC3); - } - gpu::BufferView::Size numBytes = sizeof(float) * (3 * numHullVertices); - const gpu::Byte* data = reinterpret_cast(tempVertices); - normals._buffer->append(numBytes, data); - normals._size = vertices._buffer->getSize(); - } - return true; -} - -graphics::MeshPointer createMeshFromShape(const void* pointer) { - graphics::MeshPointer mesh; - if (!pointer) { - return mesh; - } - - // pointer must be a const btCollisionShape* (cast to void*), but it only - // needs to be valid here when its render mesh is created, after this call - // the cache doesn't care what happens to the shape behind the pointer - const btCollisionShape* shape = static_cast(pointer); - - int32_t shapeType = shape->getShapeType(); - if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE || shape->isConvex()) { - // allocate buffers for it - gpu::BufferView vertices(new gpu::Buffer(), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - gpu::BufferView indices(new gpu::Buffer(), gpu::Element(gpu::SCALAR, gpu::UINT32, gpu::INDEX)); - gpu::BufferView parts(new gpu::Buffer(), gpu::Element(gpu::VEC4, gpu::UINT32, gpu::PART)); - gpu::BufferView normals(new gpu::Buffer(), gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); - - int32_t numSuccesses = 0; - if (shapeType == (int32_t)COMPOUND_SHAPE_PROXYTYPE) { - const btCompoundShape* compoundShape = static_cast(shape); - int32_t numSubShapes = compoundShape->getNumChildShapes(); - for (int32_t i = 0; i < numSubShapes; ++i) { - const btCollisionShape* childShape = compoundShape->getChildShape(i); - if (childShape->isConvex()) { - const btConvexShape* convexShape = static_cast(childShape); - if (copyShapeToMesh(compoundShape->getChildTransform(i), convexShape, vertices, indices, parts, normals)) { - numSuccesses++; - } - } - } - } else { - // shape is convex - const btConvexShape* convexShape = static_cast(shape); - btTransform transform; - transform.setIdentity(); - if (copyShapeToMesh(transform, convexShape, vertices, indices, parts, normals)) { - numSuccesses++; - } - } - if (numSuccesses > 0) { - mesh = std::make_shared(); - mesh->setVertexBuffer(vertices); - mesh->setIndexBuffer(indices); - mesh->setPartBuffer(parts); - mesh->addAttribute(gpu::Stream::NORMAL, normals); - } else { - // TODO: log failure message here - } - } - return mesh; -} - -CollisionRenderMeshCache::CollisionRenderMeshCache() { -} - -CollisionRenderMeshCache::~CollisionRenderMeshCache() { - _meshMap.clear(); - _pendingGarbage.clear(); -} - -graphics::MeshPointer CollisionRenderMeshCache::getMesh(CollisionRenderMeshCache::Key key) { - graphics::MeshPointer mesh; - if (key) { - CollisionMeshMap::const_iterator itr = _meshMap.find(key); - if (itr == _meshMap.end()) { - // make mesh and add it to map - mesh = createMeshFromShape(key); - if (mesh) { - _meshMap.insert(std::make_pair(key, mesh)); - } - } else { - mesh = itr->second; - } - } - const uint32_t MAX_NUM_PENDING_GARBAGE = 20; - if (_pendingGarbage.size() > MAX_NUM_PENDING_GARBAGE) { - collectGarbage(); - } - return mesh; -} - -bool CollisionRenderMeshCache::releaseMesh(CollisionRenderMeshCache::Key key) { - if (!key) { - return false; - } - CollisionMeshMap::const_iterator itr = _meshMap.find(key); - if (itr != _meshMap.end()) { - _pendingGarbage.push_back(key); - return true; - } - return false; -} - -void CollisionRenderMeshCache::collectGarbage() { - uint32_t numShapes = (uint32_t)_pendingGarbage.size(); - for (uint32_t i = 0; i < numShapes; ++i) { - CollisionRenderMeshCache::Key key = _pendingGarbage[i]; - CollisionMeshMap::const_iterator itr = _meshMap.find(key); - if (itr != _meshMap.end()) { - if ((*itr).second.use_count() == 1) { - // we hold the only reference - _meshMap.erase(itr); - } - } - } - _pendingGarbage.clear(); -} - diff --git a/libraries/physics/src/CollisionRenderMeshCache.h b/libraries/physics/src/CollisionRenderMeshCache.h deleted file mode 100644 index c5b643c0cc..0000000000 --- a/libraries/physics/src/CollisionRenderMeshCache.h +++ /dev/null @@ -1,48 +0,0 @@ -// -// CollisionRenderMeshCache.h -// libraries/physics/src -// -// Created by Andrew Meadows 2016.07.13 -// Copyright 2016 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_CollisionRenderMeshCache_h -#define hifi_CollisionRenderMeshCache_h - -#include -#include -#include - -#include - - -class CollisionRenderMeshCache { -public: - using Key = const void*; // must actually be a const btCollisionShape* - - CollisionRenderMeshCache(); - ~CollisionRenderMeshCache(); - - /// \return pointer to geometry - graphics::MeshPointer getMesh(Key key); - - /// \return true if geometry was found and released - bool releaseMesh(Key key); - - /// delete geometries that have zero references - void collectGarbage(); - - // validation methods - uint32_t getNumMeshes() const { return (uint32_t)_meshMap.size(); } - bool hasMesh(Key key) const { return _meshMap.find(key) == _meshMap.end(); } - -private: - using CollisionMeshMap = std::unordered_map; - CollisionMeshMap _meshMap; - std::vector _pendingGarbage; -}; - -#endif // hifi_CollisionRenderMeshCache_h diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index a610a6f2a6..925cfee740 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -307,13 +307,6 @@ const btCollisionShape* EntityMotionState::computeNewShape() { return getShapeManager()->getShape(shapeInfo); } -void EntityMotionState::setShape(const btCollisionShape* shape) { - if (_shape != shape) { - ObjectMotionState::setShape(shape); - _entity->setCollisionShape(_shape); - } -} - bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) { // NOTE: this method is only ever called when the entity simulation is locally owned DETAILED_PROFILE_RANGE(simulation_physics, "CheckOutOfSync"); diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index b215537d55..653e3f4252 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -118,7 +118,6 @@ protected: bool isReadyToComputeShape() const override; const btCollisionShape* computeNewShape() override; - void setShape(const btCollisionShape* shape) override; void setMotionType(PhysicsMotionType motionType) override; // EntityMotionState keeps a SharedPointer to its EntityItem which is only set in the CTOR diff --git a/tests/physics/src/CollisionRenderMeshCacheTests.cpp b/tests/physics/src/CollisionRenderMeshCacheTests.cpp deleted file mode 100644 index da28598dda..0000000000 --- a/tests/physics/src/CollisionRenderMeshCacheTests.cpp +++ /dev/null @@ -1,277 +0,0 @@ -// -// CollisionRenderMeshCacheTests.cpp -// tests/physics/src -// -// Created by Andrew Meadows on 2014.10.30 -// Copyright 2014 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 -// - -#include "CollisionRenderMeshCacheTests.h" - -#include -#include - -#include -#include - -#include -#include // for MAX_HULL_POINTS - -#include "MeshUtil.h" - - -QTEST_MAIN(CollisionRenderMeshCacheTests) - -const float INV_SQRT_THREE = 0.577350269f; - -const uint32_t numSphereDirections = 6 + 8; -btVector3 sphereDirections[] = { - btVector3(1.0f, 0.0f, 0.0f), - btVector3(-1.0f, 0.0f, 0.0f), - btVector3(0.0f, 1.0f, 0.0f), - btVector3(0.0f, -1.0f, 0.0f), - btVector3(0.0f, 0.0f, 1.0f), - btVector3(0.0f, 0.0f, -1.0f), - btVector3(INV_SQRT_THREE, INV_SQRT_THREE, INV_SQRT_THREE), - btVector3(INV_SQRT_THREE, INV_SQRT_THREE, -INV_SQRT_THREE), - btVector3(INV_SQRT_THREE, -INV_SQRT_THREE, INV_SQRT_THREE), - btVector3(INV_SQRT_THREE, -INV_SQRT_THREE, -INV_SQRT_THREE), - btVector3(-INV_SQRT_THREE, INV_SQRT_THREE, INV_SQRT_THREE), - btVector3(-INV_SQRT_THREE, INV_SQRT_THREE, -INV_SQRT_THREE), - btVector3(-INV_SQRT_THREE, -INV_SQRT_THREE, INV_SQRT_THREE), - btVector3(-INV_SQRT_THREE, -INV_SQRT_THREE, -INV_SQRT_THREE) -}; - -float randomFloat() { - return 2.0f * ((float)rand() / (float)RAND_MAX) - 1.0f; -} - -btBoxShape* createBoxShape(const btVector3& extent) { - btBoxShape* shape = new btBoxShape(0.5f * extent); - return shape; -} - -btConvexHullShape* createConvexHull(float radius) { - btConvexHullShape* hull = new btConvexHullShape(); - for (uint32_t i = 0; i < numSphereDirections; ++i) { - btVector3 point = radius * sphereDirections[i]; - hull->addPoint(point, false); - } - hull->recalcLocalAabb(); - return hull; -} - -void CollisionRenderMeshCacheTests::testShapeHullManifold() { - // make a box shape - btVector3 extent(1.0f, 2.0f, 3.0f); - btBoxShape* box = createBoxShape(extent); - - // wrap it with a ShapeHull - btShapeHull hull(box); - const float MARGIN = 0.0f; - hull.buildHull(MARGIN); - - // verify the vertex count is capped - uint32_t numVertices = (uint32_t)hull.numVertices(); - QVERIFY(numVertices <= MAX_HULL_POINTS); - - // verify the mesh is inside the radius - btVector3 halfExtents = box->getHalfExtentsWithMargin(); - float ACCEPTABLE_EXTENTS_ERROR = 0.01f; - float maxRadius = halfExtents.length() + ACCEPTABLE_EXTENTS_ERROR; - const btVector3* meshVertices = hull.getVertexPointer(); - for (uint32_t i = 0; i < numVertices; ++i) { - btVector3 vertex = meshVertices[i]; - QVERIFY(vertex.length() <= maxRadius); - } - - // verify the index count is capped - uint32_t numIndices = (uint32_t)hull.numIndices(); - QVERIFY(numIndices < 6 * MAX_HULL_POINTS); - - // verify the index count is a multiple of 3 - QVERIFY(numIndices % 3 == 0); - - // verify the mesh is closed - const uint32_t* meshIndices = hull.getIndexPointer(); - bool isClosed = MeshUtil::isClosedManifold(meshIndices, numIndices); - QVERIFY(isClosed); - - // verify the triangle normals are outward using right-hand-rule - const uint32_t INDICES_PER_TRIANGLE = 3; - for (uint32_t i = 0; i < numIndices; i += INDICES_PER_TRIANGLE) { - btVector3 A = meshVertices[meshIndices[i]]; - btVector3 B = meshVertices[meshIndices[i+1]]; - btVector3 C = meshVertices[meshIndices[i+2]]; - - btVector3 face = (B - A).cross(C - B); - btVector3 center = (A + B + C) / 3.0f; - QVERIFY(face.dot(center) > 0.0f); - } - - // delete unmanaged memory - delete box; -} - -void CollisionRenderMeshCacheTests::testCompoundShape() { - uint32_t numSubShapes = 3; - - btVector3 centers[] = { - btVector3(1.0f, 0.0f, 0.0f), - btVector3(0.0f, -2.0f, 0.0f), - btVector3(0.0f, 0.0f, 3.0f), - }; - - float radii[] = { 3.0f, 2.0f, 1.0f }; - - btCompoundShape* compoundShape = new btCompoundShape(); - for (uint32_t i = 0; i < numSubShapes; ++i) { - btTransform transform; - transform.setOrigin(centers[i]); - btConvexHullShape* hull = createConvexHull(radii[i]); - compoundShape->addChildShape(transform, hull); - } - - // create the cache - CollisionRenderMeshCache cache; - QVERIFY(cache.getNumMeshes() == 0); - - // get the mesh once - graphics::MeshPointer mesh = cache.getMesh(compoundShape); - QVERIFY((bool)mesh); - QVERIFY(cache.getNumMeshes() == 1); - - // get the mesh again - graphics::MeshPointer mesh2 = cache.getMesh(compoundShape); - QVERIFY(mesh2 == mesh); - QVERIFY(cache.getNumMeshes() == 1); - - // forget the mesh once - cache.releaseMesh(compoundShape); - mesh.reset(); - QVERIFY(cache.getNumMeshes() == 1); - - // collect garbage (should still cache mesh) - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 1); - - // forget the mesh a second time (should still cache mesh) - cache.releaseMesh(compoundShape); - mesh2.reset(); - QVERIFY(cache.getNumMeshes() == 1); - - // collect garbage (should no longer cache mesh) - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 0); - - // delete unmanaged memory - for (int i = 0; i < compoundShape->getNumChildShapes(); ++i) { - delete compoundShape->getChildShape(i); - } - delete compoundShape; -} - -void CollisionRenderMeshCacheTests::testMultipleShapes() { - // shapeA is compound of hulls - uint32_t numSubShapes = 3; - btVector3 centers[] = { - btVector3(1.0f, 0.0f, 0.0f), - btVector3(0.0f, -2.0f, 0.0f), - btVector3(0.0f, 0.0f, 3.0f), - }; - float radii[] = { 3.0f, 2.0f, 1.0f }; - btCompoundShape* shapeA = new btCompoundShape(); - for (uint32_t i = 0; i < numSubShapes; ++i) { - btTransform transform; - transform.setOrigin(centers[i]); - btConvexHullShape* hull = createConvexHull(radii[i]); - shapeA->addChildShape(transform, hull); - } - - // shapeB is compound of boxes - btVector3 extents[] = { - btVector3(1.0f, 2.0f, 3.0f), - btVector3(2.0f, 3.0f, 1.0f), - btVector3(3.0f, 1.0f, 2.0f), - }; - btCompoundShape* shapeB = new btCompoundShape(); - for (uint32_t i = 0; i < numSubShapes; ++i) { - btTransform transform; - transform.setOrigin(centers[i]); - btBoxShape* box = createBoxShape(extents[i]); - shapeB->addChildShape(transform, box); - } - - // shapeC is just a box - btVector3 extentC(7.0f, 3.0f, 5.0f); - btBoxShape* shapeC = createBoxShape(extentC); - - // create the cache - CollisionRenderMeshCache cache; - QVERIFY(cache.getNumMeshes() == 0); - - // get the meshes - graphics::MeshPointer meshA = cache.getMesh(shapeA); - graphics::MeshPointer meshB = cache.getMesh(shapeB); - graphics::MeshPointer meshC = cache.getMesh(shapeC); - QVERIFY((bool)meshA); - QVERIFY((bool)meshB); - QVERIFY((bool)meshC); - QVERIFY(cache.getNumMeshes() == 3); - - // get the meshes again - graphics::MeshPointer meshA2 = cache.getMesh(shapeA); - graphics::MeshPointer meshB2 = cache.getMesh(shapeB); - graphics::MeshPointer meshC2 = cache.getMesh(shapeC); - QVERIFY(meshA == meshA2); - QVERIFY(meshB == meshB2); - QVERIFY(meshC == meshC2); - QVERIFY(cache.getNumMeshes() == 3); - - // forget the meshes once - cache.releaseMesh(shapeA); - cache.releaseMesh(shapeB); - cache.releaseMesh(shapeC); - meshA2.reset(); - meshB2.reset(); - meshC2.reset(); - QVERIFY(cache.getNumMeshes() == 3); - - // collect garbage (should still cache mesh) - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 3); - - // forget again, one mesh at a time... - // shapeA... - cache.releaseMesh(shapeA); - meshA.reset(); - QVERIFY(cache.getNumMeshes() == 3); - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 2); - // shapeB... - cache.releaseMesh(shapeB); - meshB.reset(); - QVERIFY(cache.getNumMeshes() == 2); - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 1); - // shapeC... - cache.releaseMesh(shapeC); - meshC.reset(); - QVERIFY(cache.getNumMeshes() == 1); - cache.collectGarbage(); - QVERIFY(cache.getNumMeshes() == 0); - - // delete unmanaged memory - for (int i = 0; i < shapeA->getNumChildShapes(); ++i) { - delete shapeA->getChildShape(i); - } - delete shapeA; - for (int i = 0; i < shapeB->getNumChildShapes(); ++i) { - delete shapeB->getChildShape(i); - } - delete shapeB; - delete shapeC; -} diff --git a/tests/physics/src/CollisionRenderMeshCacheTests.h b/tests/physics/src/CollisionRenderMeshCacheTests.h deleted file mode 100644 index 640314a2a0..0000000000 --- a/tests/physics/src/CollisionRenderMeshCacheTests.h +++ /dev/null @@ -1,26 +0,0 @@ -// -// CollisionRenderMeshCacheTests.h -// tests/physics/src -// -// Created by Andrew Meadows on 2014.10.30 -// Copyright 2014 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_CollisionRenderMeshCacheTests_h -#define hifi_CollisionRenderMeshCacheTests_h - -#include - -class CollisionRenderMeshCacheTests : public QObject { - Q_OBJECT - -private slots: - void testShapeHullManifold(); - void testCompoundShape(); - void testMultipleShapes(); -}; - -#endif // hifi_CollisionRenderMeshCacheTests_h From c13f27e2eb96f7f9edfb5a0e93ff77e9a6f108dd Mon Sep 17 00:00:00 2001 From: Alexander Ivash Date: Tue, 24 Jul 2018 22:10:18 +0300 Subject: [PATCH 03/20] FB17023 - Make visible avatar url in the avatar app --- interface/resources/qml/hifi/AvatarApp.qml | 2 +- interface/resources/qml/hifi/avatarapp/MessageBoxes.qml | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/interface/resources/qml/hifi/AvatarApp.qml b/interface/resources/qml/hifi/AvatarApp.qml index 0a2dcb951b..a88a584c63 100644 --- a/interface/resources/qml/hifi/AvatarApp.qml +++ b/interface/resources/qml/hifi/AvatarApp.qml @@ -480,7 +480,7 @@ Rectangle { MouseArea { anchors.fill: parent onClicked: { - popup.showSpecifyAvatarUrl(function() { + popup.showSpecifyAvatarUrl(currentAvatar.avatarUrl, function() { var url = popup.inputText.text; emitSendToScript({'method' : 'applyExternalAvatar', 'avatarURL' : url}) }, function(link) { diff --git a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml index 125b30fa95..fd65d014a0 100644 --- a/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml +++ b/interface/resources/qml/hifi/avatarapp/MessageBoxes.qml @@ -3,7 +3,7 @@ import QtQuick 2.5 MessageBox { id: popup - function showSpecifyAvatarUrl(callback, linkCallback) { + function showSpecifyAvatarUrl(url, callback, linkCallback) { popup.onButton2Clicked = callback; popup.titleText = 'Specify Avatar URL' popup.bodyText = 'This will not overwrite your existing favorite if you are wearing one.
' + @@ -12,6 +12,8 @@ MessageBox { '' popup.inputText.visible = true; popup.inputText.placeholderText = 'Enter Avatar Url'; + popup.inputText.text = url; + popup.inputText.selectAll(); popup.button1text = 'CANCEL'; popup.button2text = 'CONFIRM'; From a0319f1f711c6c4af5e7942ae4f1f61105b06e8d Mon Sep 17 00:00:00 2001 From: Zach Fox Date: Tue, 24 Jul 2018 15:09:08 -0700 Subject: [PATCH 04/20] Implement MS17039: Don't delete entities during DDV when Metaverse API call returns error --- assignment-client/src/entities/EntityServer.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/assignment-client/src/entities/EntityServer.cpp b/assignment-client/src/entities/EntityServer.cpp index 8b86ba5eb2..868e570e0c 100644 --- a/assignment-client/src/entities/EntityServer.cpp +++ b/assignment-client/src/entities/EntityServer.cpp @@ -522,11 +522,8 @@ void EntityServer::startDynamicDomainVerification() { qCDebug(entities) << "Entity passed dynamic domain verification:" << entityID; } } else { - qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; deleting entity" << entityID + qCDebug(entities) << "Call to" << networkReply->url() << "failed with error" << networkReply->error() << "; NOT deleting entity" << entityID << "More info:" << jsonObject; - tree->withWriteLock([&] { - tree->deleteEntity(entityID, true); - }); } networkReply->deleteLater(); From b750a005cf8b5a2da6a829c6d27a7f9e83ee3fd9 Mon Sep 17 00:00:00 2001 From: Dante Ruiz Date: Tue, 24 Jul 2018 16:31:12 -0700 Subject: [PATCH 05/20] fix script memory issue --- assignment-client/src/Agent.cpp | 2 -- interface/src/Application.cpp | 3 --- .../script-engine/src/RecordingScriptingInterface.cpp | 8 ++++---- libraries/script-engine/src/RecordingScriptingInterface.h | 3 --- 4 files changed, 4 insertions(+), 12 deletions(-) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index 73444d1198..d61a1a49b7 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -344,8 +344,6 @@ void Agent::scriptRequestFinished() { void Agent::executeScript() { _scriptEngine = scriptEngineFactory(ScriptEngine::AGENT_SCRIPT, _scriptContents, _payload); - DependencyManager::get()->setScriptEngine(_scriptEngine); - // setup an Avatar for the script to use auto scriptedAvatar = DependencyManager::get(); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 311c08b858..af2c5d16ad 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6525,9 +6525,6 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEnginePointe entityScriptingInterface->setPacketSender(&_entityEditSender); entityScriptingInterface->setEntityTree(getEntities()->getTree()); - // give the script engine to the RecordingScriptingInterface for its callbacks - DependencyManager::get()->setScriptEngine(scriptEngine); - if (property(hifi::properties::TEST).isValid()) { scriptEngine->registerGlobalObject("Test", TestScriptingInterface::getInstance()); } diff --git a/libraries/script-engine/src/RecordingScriptingInterface.cpp b/libraries/script-engine/src/RecordingScriptingInterface.cpp index 55895e31a4..cc2edfcca7 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.cpp +++ b/libraries/script-engine/src/RecordingScriptingInterface.cpp @@ -59,7 +59,7 @@ void RecordingScriptingInterface::playClip(NetworkClipLoaderPointer clipLoader, if (callback.isFunction()) { QScriptValueList args { true, url }; - callback.call(_scriptEngine->globalObject(), args); + callback.call(QScriptValue(), args); } } @@ -78,7 +78,7 @@ void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue auto weakClipLoader = clipLoader.toWeakRef(); // when clip loaded, call the callback with the URL and success boolean - connect(clipLoader.data(), &recording::NetworkClipLoader::clipLoaded, this, + connect(clipLoader.data(), &recording::NetworkClipLoader::clipLoaded, callback.engine(), [this, weakClipLoader, url, callback]() mutable { if (auto clipLoader = weakClipLoader.toStrongRef()) { @@ -92,12 +92,12 @@ void RecordingScriptingInterface::loadRecording(const QString& url, QScriptValue }); // when clip load fails, call the callback with the URL and failure boolean - connect(clipLoader.data(), &recording::NetworkClipLoader::failed, this, [this, weakClipLoader, url, callback](QNetworkReply::NetworkError error) mutable { + connect(clipLoader.data(), &recording::NetworkClipLoader::failed, callback.engine(), [this, weakClipLoader, url, callback](QNetworkReply::NetworkError error) mutable { qCDebug(scriptengine) << "Failed to load recording from" << url; if (callback.isFunction()) { QScriptValueList args { false, url }; - callback.call(_scriptEngine->currentContext()->thisObject(), args); + callback.call(QScriptValue(), args); } if (auto clipLoader = weakClipLoader.toStrongRef()) { diff --git a/libraries/script-engine/src/RecordingScriptingInterface.h b/libraries/script-engine/src/RecordingScriptingInterface.h index 29d9b31049..c4d576351f 100644 --- a/libraries/script-engine/src/RecordingScriptingInterface.h +++ b/libraries/script-engine/src/RecordingScriptingInterface.h @@ -36,8 +36,6 @@ class RecordingScriptingInterface : public QObject, public Dependency { public: RecordingScriptingInterface(); - void setScriptEngine(QSharedPointer scriptEngine) { _scriptEngine = scriptEngine; } - public slots: /**jsdoc @@ -246,7 +244,6 @@ protected: Flag _useSkeletonModel { false }; recording::ClipPointer _lastClip; - QSharedPointer _scriptEngine; QSet _clipLoaders; private: From 4750611af9a9d3a1ca924599413b9476dea4fbca Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Tue, 24 Jul 2018 23:47:58 -0700 Subject: [PATCH 06/20] particles don't spin with head roll, add particle spin properties, negative emitSpeed --- .../RenderableParticleEffectEntityItem.cpp | 4 ++ .../src/RenderableParticleEffectEntityItem.h | 1 + .../src/textured_particle.slv | 59 +++++++++++---- .../entities/src/EntityItemProperties.cpp | 52 ++++++++++++++ libraries/entities/src/EntityItemProperties.h | 5 ++ libraries/entities/src/EntityPropertyFlags.h | 5 ++ .../entities/src/ParticleEffectEntityItem.cpp | 71 ++++++++++++++++++- .../entities/src/ParticleEffectEntityItem.h | 22 +++++- .../networking/src/udt/PacketHeaders.cpp | 2 +- libraries/networking/src/udt/PacketHeaders.h | 3 +- .../particle_explorer/particleExplorer.js | 42 +++++++++++ .../particle_explorer/particleExplorerTool.js | 10 ++- 12 files changed, 255 insertions(+), 21 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 309671f49e..89c2f0dccf 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -144,6 +144,10 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn particleUniforms.color.middle = _particleProperties.getColorMiddle(); particleUniforms.color.finish = _particleProperties.getColorFinish(); particleUniforms.color.spread = _particleProperties.getColorSpread(); + particleUniforms.spin.start = _particleProperties.spin.range.start; + particleUniforms.spin.middle = _particleProperties.spin.gradient.target; + particleUniforms.spin.finish = _particleProperties.spin.range.finish; + particleUniforms.spin.spread = _particleProperties.spin.gradient.spread; particleUniforms.lifespan = _particleProperties.lifespan; }); // Update particle uniforms diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index 8e9353894a..e1e3cd210e 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -74,6 +74,7 @@ private: struct ParticleUniforms { InterpolationData radius; InterpolationData color; // rgba + InterpolationData spin; float lifespan; glm::vec3 spare; }; diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index 7653bc0a42..bc3ef4fbb0 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -27,10 +27,17 @@ struct Colors { vec4 finish; vec4 spread; }; +struct Spin { + float start; + float middle; + float finish; + float spread; +}; struct ParticleUniforms { Radii radius; Colors color; + Spin spin; vec4 lifespan; // x is lifespan, 3 spare floats }; @@ -44,15 +51,6 @@ layout(location=2) in vec2 inColor; // This is actual Lifetime + Seed out vec4 varColor; out vec2 varTexcoord; -const int NUM_VERTICES_PER_PARTICLE = 4; -// This ordering ensures that un-rotated particles render upright in the viewer. -const vec4 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec4[NUM_VERTICES_PER_PARTICLE]( - vec4(-1.0, 1.0, 0.0, 0.0), - vec4(-1.0, -1.0, 0.0, 0.0), - vec4(1.0, 1.0, 0.0, 0.0), - vec4(1.0, -1.0, 0.0, 0.0) -); - float bezierInterpolate(float y1, float y2, float y3, float u) { // https://en.wikipedia.org/wiki/Bezier_curve return (1.0 - u) * (1.0 - u) * y1 + 2.0 * (1.0 - u) * u * y2 + u * u * y3; @@ -103,6 +101,15 @@ vec4 interpolate3Vec4(vec4 y1, vec4 y2, vec4 y3, float u) { interpolate3Points(y1.w, y2.w, y3.w, u)); } +const int NUM_VERTICES_PER_PARTICLE = 4; +const vec2 TEX_COORDS[NUM_VERTICES_PER_PARTICLE] = vec2[NUM_VERTICES_PER_PARTICLE]( + vec2(-1.0, 0.0), + vec2(-1.0, 1.0), + vec2(0.0, 0.0), + vec2(0.0, 1.0) +); + + void main(void) { TransformCamera cam = getTransformCamera(); TransformObject obj = getTransformObject(); @@ -116,25 +123,47 @@ void main(void) { float age = inColor.x / particle.lifespan.x; float seed = inColor.y; - // Pass the texcoord and the z texcoord is representing the texture icon - // Offset for corrected vertex ordering. - varTexcoord = vec2((UNIT_QUAD[twoTriID].xy -1.0) * vec2(0.5, -0.5)); + // Pass the texcoord + varTexcoord = TEX_COORDS[twoTriID].xy; varColor = interpolate3Vec4(particle.color.start, particle.color.middle, particle.color.finish, age); vec3 colorSpread = 2.0 * vec3(hifi_hash(seed), hifi_hash(seed * 2.0), hifi_hash(seed * 3.0)) - 1.0; varColor.rgb = clamp(varColor.rgb + colorSpread * particle.color.spread.rgb, vec3(0), vec3(1)); float alphaSpread = 2.0 * hifi_hash(seed * 4.0) - 1.0; varColor.a = clamp(varColor.a + alphaSpread * particle.color.spread.a, 0.0, 1.0); + float spin = interpolate3Points(particle.spin.start, particle.spin.middle, particle.spin.finish, age); + float spinSpread = 2.0 * hifi_hash(seed * 5.0) - 1.0; + spin = spin + spinSpread * particle.spin.spread; + // anchor point in eye space float radius = interpolate3Points(particle.radius.start, particle.radius.middle, particle.radius.finish, age); - float radiusSpread = 2.0 * hifi_hash(seed * 5.0) - 1.0; + float radiusSpread = 2.0 * hifi_hash(seed * 6.0) - 1.0; radius = max(radius + radiusSpread * particle.radius.spread, 0.0); - vec4 quadPos = radius * UNIT_QUAD[twoTriID]; vec4 anchorPoint; vec4 _inPosition = vec4(inPosition, 1.0); <$transformModelToEyePos(cam, obj, _inPosition, anchorPoint)$> - vec4 eyePos = anchorPoint + quadPos; + mat3 view3 = mat3(cam._view); + vec3 worldUpEye = normalize(view3 * vec3(0, 1, 0)); + vec3 right = cross(vec3(0, 0, -1), worldUpEye); + vec3 up = cross(right, vec3(0, 0, -1)); + // This ordering ensures that un-rotated particles render upright in the viewer. + vec3 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec3[NUM_VERTICES_PER_PARTICLE]( + normalize(-right + up), + normalize(-right - up), + normalize(right + up), + normalize(right - up) + ); + float c = cos(spin); + float s = sin(spin); + mat4 rotation = mat4( + c, -s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + ); + vec4 quadPos = radius * vec4(UNIT_QUAD[twoTriID], 0.0); + vec4 eyePos = anchorPoint + rotation * quadPos; <$transformEyeToClipPos(cam, eyePos, gl_Position)$> } diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index efd2376677..929adb2c37 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -369,6 +369,10 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_MATERIAL_MAPPING_ROT, materialMappingRot); CHECK_PROPERTY_CHANGE(PROP_MATERIAL_DATA, materialData); CHECK_PROPERTY_CHANGE(PROP_VISIBLE_IN_SECONDARY_CAMERA, isVisibleInSecondaryCamera); + CHECK_PROPERTY_CHANGE(PROP_PARTICLE_SPIN, particleSpin); + CHECK_PROPERTY_CHANGE(PROP_SPIN_SPREAD, spinSpread); + CHECK_PROPERTY_CHANGE(PROP_SPIN_START, spinStart); + CHECK_PROPERTY_CHANGE(PROP_SPIN_FINISH, spinFinish); // Certifiable Properties CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); @@ -908,6 +912,13 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * alpha value is used. * @property {number} alphaSpread=0 - The spread in alpha that each particle is given. If alpha == 0.5 * and alphaSpread == 0.25, each particle will have an alpha in the range 0.250.75. + * @property {number} particleSpin=0 - The spin of each particle at the middle of its life. -2*PI - 2*PI. + * @property {number} spinStart=null - The spin of each particle at the start of its life. In the range -2*PI2*PI. + * If null, the particleSpin value is used. + * @property {number} spinFinish=null - The spin of each particle at the end of its life. In the range -2*PI2*PI. + * If null, the particleSpin value is used. + * @property {number} spinSpread=0 - The spread in spin that each particle is given. -2*PI - 2*PI. If particleSpin == PI + * and spinSpread == PI/2, each particle will have a spin in the range PI/23*PI/2. * * @property {ShapeType} shapeType="none" - Currently not used. Read-only. * @@ -1291,6 +1302,10 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_START, alphaStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_ALPHA_FINISH, alphaFinish); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_EMITTER_SHOULD_TRAIL, emitterShouldTrail); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_SPIN, particleSpin); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_SPREAD, spinSpread); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_START, spinStart); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_FINISH, spinFinish); } // Models only @@ -1583,6 +1598,10 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(materialMappingRot, float, setMaterialMappingRot); COPY_PROPERTY_FROM_QSCRIPTVALUE(materialData, QString, setMaterialData); COPY_PROPERTY_FROM_QSCRIPTVALUE(isVisibleInSecondaryCamera, bool, setIsVisibleInSecondaryCamera); + COPY_PROPERTY_FROM_QSCRIPTVALUE(particleSpin, float, setParticleSpin); + COPY_PROPERTY_FROM_QSCRIPTVALUE(spinSpread, float, setSpinSpread); + COPY_PROPERTY_FROM_QSCRIPTVALUE(spinStart, float, setSpinStart); + COPY_PROPERTY_FROM_QSCRIPTVALUE(spinFinish, float, setSpinFinish); // Certifiable Properties COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); @@ -1751,6 +1770,10 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(radiusSpread); COPY_PROPERTY_IF_CHANGED(radiusStart); COPY_PROPERTY_IF_CHANGED(radiusFinish); + COPY_PROPERTY_IF_CHANGED(particleSpin); + COPY_PROPERTY_IF_CHANGED(spinSpread); + COPY_PROPERTY_IF_CHANGED(spinStart); + COPY_PROPERTY_IF_CHANGED(spinFinish); // Certifiable Properties COPY_PROPERTY_IF_CHANGED(itemName); @@ -1964,6 +1987,11 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool); + ADD_PROPERTY_TO_MAP(PROP_PARTICLE_SPIN, ParticleSpin, particleSpin, float); + ADD_PROPERTY_TO_MAP(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float); + ADD_PROPERTY_TO_MAP(PROP_SPIN_START, SpinStart, spinStart, float); + ADD_PROPERTY_TO_MAP(PROP_SPIN_FINISH, SpinFinish, spinFinish, float); + // Certifiable Properties ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); ADD_PROPERTY_TO_MAP(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString); @@ -2292,6 +2320,10 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_ALPHA_START, properties.getAlphaStart()); APPEND_ENTITY_PROPERTY(PROP_ALPHA_FINISH, properties.getAlphaFinish()); APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, properties.getEmitterShouldTrail()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, properties.getParticleSpin()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, properties.getSpinSpread()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_START, properties.getSpinStart()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_FINISH, properties.getSpinFinish()); } if (properties.getType() == EntityTypes::Zone) { @@ -2667,6 +2699,10 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_START, float, setAlphaStart); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ALPHA_FINISH, float, setAlphaFinish); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_SPIN, float, setParticleSpin); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_SPREAD, float, setSpinSpread); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_START, float, setSpinStart); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_FINISH, float, setSpinFinish); } if (properties.getType() == EntityTypes::Zone) { @@ -2961,6 +2997,10 @@ void EntityItemProperties::markAllChanged() { _colorFinishChanged = true; _alphaStartChanged = true; _alphaFinishChanged = true; + _particleSpinChanged = true; + _spinStartChanged = true; + _spinFinishChanged = true; + _spinSpreadChanged = true; _materialURLChanged = true; _materialMappingModeChanged = true; @@ -3309,6 +3349,18 @@ QList EntityItemProperties::listChangedProperties() { if (radiusFinishChanged()) { out += "radiusFinish"; } + if (particleSpinChanged()) { + out += "particleSpin"; + } + if (spinSpreadChanged()) { + out += "spinSpread"; + } + if (spinStartChanged()) { + out += "spinStart"; + } + if (spinFinishChanged()) { + out += "spinFinish"; + } if (materialURLChanged()) { out += "materialURL"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 93b8c991d5..7799d45b22 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -235,6 +235,11 @@ public: DEFINE_PROPERTY(PROP_VISIBLE_IN_SECONDARY_CAMERA, IsVisibleInSecondaryCamera, isVisibleInSecondaryCamera, bool, ENTITY_ITEM_DEFAULT_VISIBLE_IN_SECONDARY_CAMERA); + DEFINE_PROPERTY(PROP_PARTICLE_SPIN, ParticleSpin, particleSpin, float, particle::DEFAULT_PARTICLE_SPIN); + DEFINE_PROPERTY(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float, particle::DEFAULT_SPIN_SPREAD); + DEFINE_PROPERTY(PROP_SPIN_START, SpinStart, spinStart, float, particle::DEFAULT_SPIN_START); + DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH) + // Certifiable Properties - related to Proof of Purchase certificates DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); DEFINE_PROPERTY_REF(PROP_ITEM_DESCRIPTION, ItemDescription, itemDescription, QString, ENTITY_ITEM_DEFAULT_ITEM_DESCRIPTION); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index d43a991f22..bece248fe7 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -251,6 +251,11 @@ enum EntityPropertyList { PROP_VISIBLE_IN_SECONDARY_CAMERA, // not sent over the wire, only used locally + PROP_PARTICLE_SPIN, + PROP_SPIN_START, + PROP_SPIN_FINISH, + PROP_SPIN_SPREAD, + //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line PROP_AFTER_LAST_ITEM, diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index 18cf7c9252..c1785639e0 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -91,6 +91,7 @@ bool operator==(const Properties& a, const Properties& b) { (a.color == b.color) && (a.alpha == b.alpha) && (a.radius == b.radius) && + (a.spin == b.spin) && (a.radiusStart == b.radiusStart) && (a.lifespan == b.lifespan) && (a.maxParticles == b.maxParticles) && @@ -130,7 +131,11 @@ bool Properties::valid() const { (radius.gradient.target == glm::clamp(radius.gradient.target, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS)) && (radius.range.start == glm::clamp(radius.range.start, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS)) && (radius.range.finish == glm::clamp(radius.range.finish, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS)) && - (radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS)); + (radius.gradient.spread == glm::clamp(radius.gradient.spread, MINIMUM_PARTICLE_RADIUS, MAXIMUM_PARTICLE_RADIUS)) && + (spin.gradient.target == glm::clamp(spin.gradient.target, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN)) && + (spin.range.start == glm::clamp(spin.range.start, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN)) && + (spin.range.finish == glm::clamp(spin.range.finish, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN)) && + (spin.gradient.spread == glm::clamp(spin.gradient.spread, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN)); } bool Properties::emitting() const { @@ -332,6 +337,43 @@ void ParticleEffectEntityItem::setRadiusSpread(float radiusSpread) { } } +void ParticleEffectEntityItem::setParticleSpin(float particleSpin) { + particleSpin = glm::clamp(particleSpin, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN); + if (particleSpin != _particleProperties.spin.gradient.target) { + withWriteLock([&] { + _particleProperties.spin.gradient.target = particleSpin; + }); + } +} + +void ParticleEffectEntityItem::setSpinStart(float spinStart) { + spinStart = + glm::isnan(spinStart) ? spinStart : glm::clamp(spinStart, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN); + if (spinStart != _particleProperties.spin.range.start) { + withWriteLock([&] { + _particleProperties.spin.range.start = spinStart; + }); + } +} + +void ParticleEffectEntityItem::setSpinFinish(float spinFinish) { + spinFinish = + glm::isnan(spinFinish) ? spinFinish : glm::clamp(spinFinish, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN); + if (spinFinish != _particleProperties.spin.range.finish) { + withWriteLock([&] { + _particleProperties.spin.range.finish = spinFinish; + }); + } +} + +void ParticleEffectEntityItem::setSpinSpread(float spinSpread) { + spinSpread = glm::clamp(spinSpread, MINIMUM_PARTICLE_SPIN, MAXIMUM_PARTICLE_SPIN); + if (spinSpread != _particleProperties.spin.gradient.spread) { + withWriteLock([&] { + _particleProperties.spin.gradient.spread = spinSpread; + }); + } +} void ParticleEffectEntityItem::computeAndUpdateDimensions() { particle::Properties particleProperties; @@ -398,6 +440,10 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(alphaFinish, getAlphaFinish); COPY_ENTITY_PROPERTY_TO_PROPERTIES(textures, getTextures); COPY_ENTITY_PROPERTY_TO_PROPERTIES(emitterShouldTrail, getEmitterShouldTrail); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(particleSpin, getParticleSpin); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinSpread, getSpinSpread); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinStart, getSpinStart); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinFinish, getSpinFinish); return properties; } @@ -435,6 +481,10 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(alphaFinish, setAlphaFinish); SET_ENTITY_PROPERTY_FROM_PROPERTIES(textures, setTextures); SET_ENTITY_PROPERTY_FROM_PROPERTIES(emitterShouldTrail, setEmitterShouldTrail); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(particleSpin, setParticleSpin); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinSpread, setSpinSpread); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinStart, setSpinStart); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinFinish, setSpinFinish); if (somethingChanged) { bool wantDebug = false; @@ -515,6 +565,11 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, bool, setEmitterShouldTrail); + READ_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, float, setParticleSpin); + READ_ENTITY_PROPERTY(PROP_SPIN_SPREAD, float, setSpinSpread); + READ_ENTITY_PROPERTY(PROP_SPIN_START, float, setSpinStart); + READ_ENTITY_PROPERTY(PROP_SPIN_FINISH, float, setSpinFinish); + return bytesRead; } @@ -551,6 +606,10 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_AZIMUTH_START; requestedProperties += PROP_AZIMUTH_FINISH; requestedProperties += PROP_EMITTER_SHOULD_TRAIL; + requestedProperties += PROP_PARTICLE_SPIN; + requestedProperties += PROP_SPIN_SPREAD; + requestedProperties += PROP_SPIN_START; + requestedProperties += PROP_SPIN_FINISH; return requestedProperties; } @@ -594,6 +653,10 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_START, getAzimuthStart()); APPEND_ENTITY_PROPERTY(PROP_AZIMUTH_FINISH, getAzimuthFinish()); APPEND_ENTITY_PROPERTY(PROP_EMITTER_SHOULD_TRAIL, getEmitterShouldTrail()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_SPIN, getParticleSpin()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, getSpinSpread()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_START, getSpinStart()); + APPEND_ENTITY_PROPERTY(PROP_SPIN_FINISH, getSpinFinish()); } @@ -689,6 +752,12 @@ particle::Properties ParticleEffectEntityItem::getParticleProperties() const { if (glm::isnan(result.radius.range.finish)) { result.radius.range.finish = getParticleRadius(); } + if (glm::isnan(result.spin.range.start)) { + result.spin.range.start = getParticleSpin(); + } + if (glm::isnan(result.spin.range.finish)) { + result.spin.range.finish = getParticleSpin(); + } }); if (!result.valid()) { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index 7e507ab46a..e4120eed63 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -39,7 +39,7 @@ namespace particle { static const float MINIMUM_EMIT_RATE = 0.0f; static const float MAXIMUM_EMIT_RATE = 100000.0f; static const float DEFAULT_EMIT_SPEED = 5.0f; - static const float MINIMUM_EMIT_SPEED = 0.0f; + static const float MINIMUM_EMIT_SPEED = -1000.0f; static const float MAXIMUM_EMIT_SPEED = 1000.0f; // Approx mach 3 static const float DEFAULT_SPEED_SPREAD = 1.0f; static const glm::quat DEFAULT_EMIT_ORIENTATION = glm::angleAxis(-PI_OVER_TWO, Vectors::UNIT_X); // Vertical @@ -69,6 +69,12 @@ namespace particle { static const float DEFAULT_RADIUS_SPREAD = 0.0f; static const float DEFAULT_RADIUS_START = UNINITIALIZED; static const float DEFAULT_RADIUS_FINISH = UNINITIALIZED; + static const float DEFAULT_PARTICLE_SPIN = 0.0f; + static const float DEFAULT_SPIN_START = UNINITIALIZED; + static const float DEFAULT_SPIN_FINISH = UNINITIALIZED; + static const float DEFAULT_SPIN_SPREAD = 0.0f; + static const float MINIMUM_PARTICLE_SPIN = -2.0f * SCRIPT_MAXIMUM_PI; + static const float MAXIMUM_PARTICLE_SPIN = 2.0f * SCRIPT_MAXIMUM_PI; static const QString DEFAULT_TEXTURES = ""; static const bool DEFAULT_EMITTER_SHOULD_TRAIL = false; @@ -151,6 +157,7 @@ namespace particle { RangeGradient alpha { DEFAULT_ALPHA, DEFAULT_ALPHA_START, DEFAULT_ALPHA_FINISH, DEFAULT_ALPHA_SPREAD }; float radiusStart { DEFAULT_EMIT_RADIUS_START }; RangeGradient radius { DEFAULT_PARTICLE_RADIUS, DEFAULT_RADIUS_START, DEFAULT_RADIUS_FINISH, DEFAULT_RADIUS_SPREAD }; + RangeGradient spin { DEFAULT_PARTICLE_SPIN, DEFAULT_SPIN_START, DEFAULT_SPIN_FINISH, DEFAULT_SPIN_SPREAD }; float lifespan { DEFAULT_LIFESPAN }; uint32_t maxParticles { DEFAULT_MAX_PARTICLES }; EmitProperties emission; @@ -168,6 +175,7 @@ namespace particle { Properties& operator =(const Properties& other) { color = other.color; alpha = other.alpha; + spin = other.spin; radius = other.radius; lifespan = other.lifespan; maxParticles = other.maxParticles; @@ -306,6 +314,18 @@ public: void setRadiusSpread(float radiusSpread); float getRadiusSpread() const { return _particleProperties.radius.gradient.spread; } + void setParticleSpin(float particleSpin); + float getParticleSpin() const { return _particleProperties.spin.gradient.target; } + + void setSpinStart(float spinStart); + float getSpinStart() const { return _particleProperties.spin.range.start; } + + void setSpinFinish(float spinFinish); + float getSpinFinish() const { return _particleProperties.spin.range.finish; } + + void setSpinSpread(float spinSpread); + float getSpinSpread() const { return _particleProperties.spin.gradient.spread; } + void computeAndUpdateDimensions(); void setTextures(const QString& textures); diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index 13ffcb5120..d0bd7fc872 100644 --- a/libraries/networking/src/udt/PacketHeaders.cpp +++ b/libraries/networking/src/udt/PacketHeaders.cpp @@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) { case PacketType::EntityEdit: case PacketType::EntityData: case PacketType::EntityPhysics: - return static_cast(EntityVersion::ParticleEntityFix); + return static_cast(EntityVersion::ParticleSpin); case PacketType::EntityQuery: return static_cast(EntityQueryPacketVersion::ConicalFrustums); case PacketType::AvatarIdentity: diff --git a/libraries/networking/src/udt/PacketHeaders.h b/libraries/networking/src/udt/PacketHeaders.h index 6e1aca83e5..2ffadfef4b 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -238,7 +238,8 @@ enum class EntityVersion : PacketVersion { CloneableData, CollisionMask16Bytes, YieldSimulationOwnership, - ParticleEntityFix + ParticleEntityFix, + ParticleSpin }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js index cb2c2f3374..b3a4461e69 100644 --- a/scripts/system/particle_explorer/particleExplorer.js +++ b/scripts/system/particle_explorer/particleExplorer.js @@ -361,6 +361,48 @@ type: "Row" } ], + Spim: [ + { + id: "particleSpin", + name: "Particle Spin", + type: "SliderRadian", + min: -360.0, + max: 360.0 + }, + { + type: "Row" + }, + { + id: "spinSpread", + name: "Spin Spread", + type: "SliderRadian", + min: -360.0, + max: 360.0 + }, + { + type: "Row" + }, + { + id: "spinStart", + name: "Spin Start", + type: "SliderRadian", + min: -360.0, + max: 360.0 + }, + { + type: "Row" + }, + { + id: "spinFinish", + name: "Spin Finish", + type: "SliderRadian", + min: -360.0, + max: 360.0 + }, + { + type: "Row" + } + ], Polar: [ { id: "polarStart", diff --git a/scripts/system/particle_explorer/particleExplorerTool.js b/scripts/system/particle_explorer/particleExplorerTool.js index 1914180ff9..a3be004329 100644 --- a/scripts/system/particle_explorer/particleExplorerTool.js +++ b/scripts/system/particle_explorer/particleExplorerTool.js @@ -75,6 +75,12 @@ ParticleExplorerTool = function(createToolsWindow) { if (isNaN(properties.colorFinish.red)) { properties.colorFinish = properties.color; } + if (isNaN(properties.spinStart)) { + properties.spinStart = properties.particleSpin; + } + if (isNaN(properties.spinFinish)) { + properties.spinFinish = properties.particleSpin; + } sendParticleProperties(properties); } @@ -88,8 +94,8 @@ ParticleExplorerTool = function(createToolsWindow) { if (data.messageType === "settings_update") { var updatedSettings = data.updatedSettings; - var optionalProps = ["alphaStart", "alphaFinish", "radiusStart", "radiusFinish", "colorStart", "colorFinish"]; - var fallbackProps = ["alpha", "particleRadius", "color"]; + var optionalProps = ["alphaStart", "alphaFinish", "radiusStart", "radiusFinish", "colorStart", "colorFinish", "spinStart", "spinFinish"]; + var fallbackProps = ["alpha", "particleRadius", "color", "particleSpin"]; for (var i = 0; i < optionalProps.length; i++) { var fallbackProp = fallbackProps[Math.floor(i / 2)]; var optionalValue = updatedSettings[optionalProps[i]]; From b4cc9c800442b8f282220c0ca4c8e21801235641 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 25 Jul 2018 09:36:43 -0700 Subject: [PATCH 07/20] typo --- scripts/system/particle_explorer/particleExplorer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js index b3a4461e69..50d3beaeae 100644 --- a/scripts/system/particle_explorer/particleExplorer.js +++ b/scripts/system/particle_explorer/particleExplorer.js @@ -361,7 +361,7 @@ type: "Row" } ], - Spim: [ + Spin: [ { id: "particleSpin", name: "Particle Spin", From 2aeef2e016f99230eca6b3338bd44529e61b8db2 Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 25 Jul 2018 09:40:52 -0700 Subject: [PATCH 08/20] min spinSpread is 0 --- scripts/system/particle_explorer/particleExplorer.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js index 50d3beaeae..a6cbbc14cb 100644 --- a/scripts/system/particle_explorer/particleExplorer.js +++ b/scripts/system/particle_explorer/particleExplorer.js @@ -376,7 +376,6 @@ id: "spinSpread", name: "Spin Spread", type: "SliderRadian", - min: -360.0, max: 360.0 }, { From d29332595b9ac6496522e25b609c780480f9583a Mon Sep 17 00:00:00 2001 From: Sam Gondelman Date: Wed, 25 Jul 2018 09:54:14 -0700 Subject: [PATCH 09/20] jsdoc fixes --- libraries/entities/src/EntityItemProperties.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 929adb2c37..f86c7a18b7 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -912,12 +912,12 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * alpha value is used. * @property {number} alphaSpread=0 - The spread in alpha that each particle is given. If alpha == 0.5 * and alphaSpread == 0.25, each particle will have an alpha in the range 0.250.75. - * @property {number} particleSpin=0 - The spin of each particle at the middle of its life. -2*PI - 2*PI. + * @property {number} particleSpin=0 - The spin of each particle at the middle of its life. In the range -2*PI2*PI. * @property {number} spinStart=null - The spin of each particle at the start of its life. In the range -2*PI2*PI. * If null, the particleSpin value is used. * @property {number} spinFinish=null - The spin of each particle at the end of its life. In the range -2*PI2*PI. * If null, the particleSpin value is used. - * @property {number} spinSpread=0 - The spread in spin that each particle is given. -2*PI - 2*PI. If particleSpin == PI + * @property {number} spinSpread=0 - The spread in spin that each particle is given. In the range 02*PI. If particleSpin == PI * and spinSpread == PI/2, each particle will have a spin in the range PI/23*PI/2. * * @property {ShapeType} shapeType="none" - Currently not used. Read-only. From c5599623f7913905c11f5d9d1f2804dff84a4954 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 25 Jul 2018 10:29:29 -0700 Subject: [PATCH 10/20] added a reset when the hips go below 1/3 of the default avatar height of the hips also reset the vertical this prevents real life sitting --- interface/src/avatar/MyAvatar.cpp | 18 +++++++++++++++--- interface/src/avatar/MyAvatar.h | 4 ++-- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bf7276d5d5..1dc4e82acc 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3042,7 +3042,7 @@ static glm::vec3 dampenCgMovement(glm::vec3 cgUnderHeadHandsAvatarSpace, float b } // computeCounterBalance returns the center of gravity in Avatar space -glm::vec3 MyAvatar::computeCounterBalance() const { +glm::vec3 MyAvatar::computeCounterBalance() { struct JointMass { QString name; float weight; @@ -3061,6 +3061,7 @@ glm::vec3 MyAvatar::computeCounterBalance() const { JointMass cgRightHandMass(QString("RightHand"), DEFAULT_AVATAR_RIGHTHAND_MASS, glm::vec3(0.0f, 0.0f, 0.0f)); glm::vec3 tposeHead = DEFAULT_AVATAR_HEAD_POS; glm::vec3 tposeHips = glm::vec3(0.0f, 0.0f, 0.0f); + glm::vec3 tposeRightFoot = glm::vec3(0.0f, -1.0f, 0.0f); if (_skeletonModel->getRig().indexOfJoint(cgHeadMass.name) != -1) { cgHeadMass.position = getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgHeadMass.name)); @@ -3079,6 +3080,9 @@ glm::vec3 MyAvatar::computeCounterBalance() const { if (_skeletonModel->getRig().indexOfJoint("Hips") != -1) { tposeHips = getAbsoluteDefaultJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint("Hips")); } + if (_skeletonModel->getRig().indexOfJoint("RightFoot") != -1) { + tposeRightFoot = getAbsoluteDefaultJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint("RightFoot")); + } // find the current center of gravity position based on head and hand moments glm::vec3 sumOfMoments = (cgHeadMass.weight * cgHeadMass.position) + (cgLeftHandMass.weight * cgLeftHandMass.position) + (cgRightHandMass.weight * cgRightHandMass.position); @@ -3102,6 +3106,8 @@ glm::vec3 MyAvatar::computeCounterBalance() const { glm::vec3 xzDiff((cgHeadMass.position.x - counterBalancedCg.x), 0.0f, (cgHeadMass.position.z - counterBalancedCg.z)); float headMinusHipXz = glm::length(xzDiff); float headHipDefault = glm::length(tposeHead - tposeHips); + float hipFootDefault = glm::length(tposeHips - tposeRightFoot); + float sitSquatThreshold = tposeHips.y - (0.333f)*hipFootDefault; float hipHeight = 0.0f; if (headHipDefault > headMinusHipXz) { hipHeight = sqrtf((headHipDefault * headHipDefault) - (headMinusHipXz * headMinusHipXz)); @@ -3113,6 +3119,12 @@ glm::vec3 MyAvatar::computeCounterBalance() const { if (counterBalancedCg.y > (tposeHips.y + 0.05f)) { // if the height is higher than default hips, clamp to default hips counterBalancedCg.y = tposeHips.y + 0.05f; + } else if (counterBalancedCg.y < sitSquatThreshold) { + //do a height reset + setResetMode(true); + _follow.activate(FollowHelper::Vertical); + qCDebug(interfaceapp) << "doing a reset for sitting"; + } return counterBalancedCg; } @@ -3162,7 +3174,7 @@ static void drawBaseOfSupport(float baseOfSupportScale, float footLocal, glm::ma // this function finds the hips position using a center of gravity model that // balances the head and hands with the hips over the base of support // returns the rotation (-z forward) and position of the Avatar in Sensor space -glm::mat4 MyAvatar::deriveBodyUsingCgModel() const { +glm::mat4 MyAvatar::deriveBodyUsingCgModel() { glm::mat4 sensorToWorldMat = getSensorToWorldMatrix(); glm::mat4 worldToSensorMat = glm::inverse(sensorToWorldMat); auto headPose = getControllerPoseInSensorFrame(controller::Action::HEAD); @@ -3180,7 +3192,7 @@ glm::mat4 MyAvatar::deriveBodyUsingCgModel() const { } // get the new center of gravity - const glm::vec3 cgHipsPosition = computeCounterBalance(); + glm::vec3 cgHipsPosition = computeCounterBalance(); // find the new hips rotation using the new head-hips axis as the up axis glm::mat4 avatarHipsMat = computeNewHipsMatrix(glmExtractRotation(avatarHeadMat), extractTranslation(avatarHeadMat), cgHipsPosition); diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index add00962da..da16759a5e 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1017,12 +1017,12 @@ public: // results are in sensor frame (-z forward) glm::mat4 deriveBodyFromHMDSensor() const; - glm::vec3 computeCounterBalance() const; + glm::vec3 computeCounterBalance(); // derive avatar body position and orientation from using the current HMD Sensor location in relation to the previous // location of the base of support of the avatar. // results are in sensor frame (-z foward) - glm::mat4 deriveBodyUsingCgModel() const; + glm::mat4 deriveBodyUsingCgModel(); /**jsdoc * @function MyAvatar.isUp From 37540c79b34f39377088f4367fb253ba62056f27 Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 25 Jul 2018 10:51:19 -0700 Subject: [PATCH 11/20] removed print statement and added const upper leg fraction --- interface/src/avatar/MyAvatar.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 1dc4e82acc..c9e268f418 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3103,11 +3103,12 @@ glm::vec3 MyAvatar::computeCounterBalance() { glm::vec3 counterBalancedCg = (1.0f / DEFAULT_AVATAR_HIPS_MASS) * counterBalancedForHead; // find the height of the hips + const float UPPER_LEG_FRACTION = 0.3333f; glm::vec3 xzDiff((cgHeadMass.position.x - counterBalancedCg.x), 0.0f, (cgHeadMass.position.z - counterBalancedCg.z)); float headMinusHipXz = glm::length(xzDiff); float headHipDefault = glm::length(tposeHead - tposeHips); float hipFootDefault = glm::length(tposeHips - tposeRightFoot); - float sitSquatThreshold = tposeHips.y - (0.333f)*hipFootDefault; + float sitSquatThreshold = tposeHips.y - (UPPER_LEG_FRACTION*hipFootDefault); float hipHeight = 0.0f; if (headHipDefault > headMinusHipXz) { hipHeight = sqrtf((headHipDefault * headHipDefault) - (headMinusHipXz * headMinusHipXz)); @@ -3120,11 +3121,9 @@ glm::vec3 MyAvatar::computeCounterBalance() { // if the height is higher than default hips, clamp to default hips counterBalancedCg.y = tposeHips.y + 0.05f; } else if (counterBalancedCg.y < sitSquatThreshold) { - //do a height reset + //do a height reset setResetMode(true); _follow.activate(FollowHelper::Vertical); - qCDebug(interfaceapp) << "doing a reset for sitting"; - } return counterBalancedCg; } From 85b7a9b67cfdc21ff4cf0b055c160d0a84d56c6c Mon Sep 17 00:00:00 2001 From: amantley Date: Wed, 25 Jul 2018 11:31:02 -0700 Subject: [PATCH 12/20] added the changes committed to the hot fix rc70.1 in AvatarConstants.h --- libraries/shared/src/AvatarConstants.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libraries/shared/src/AvatarConstants.h b/libraries/shared/src/AvatarConstants.h index 3dc344dc6f..d9b26927e2 100644 --- a/libraries/shared/src/AvatarConstants.h +++ b/libraries/shared/src/AvatarConstants.h @@ -23,10 +23,10 @@ const float DEFAULT_AVATAR_EYE_HEIGHT = DEFAULT_AVATAR_HEIGHT - DEFAULT_AVATAR_E const float DEFAULT_AVATAR_SUPPORT_BASE_LEFT = -0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_RIGHT = 0.25f; const float DEFAULT_AVATAR_SUPPORT_BASE_FRONT = -0.20f; -const float DEFAULT_AVATAR_SUPPORT_BASE_BACK = 0.10f; +const float DEFAULT_AVATAR_SUPPORT_BASE_BACK = 0.12f; const float DEFAULT_AVATAR_LATERAL_STEPPING_THRESHOLD = 0.10f; const float DEFAULT_AVATAR_ANTERIOR_STEPPING_THRESHOLD = 0.04f; -const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.07f; +const float DEFAULT_AVATAR_POSTERIOR_STEPPING_THRESHOLD = 0.05f; const float DEFAULT_AVATAR_HEAD_ANGULAR_VELOCITY_STEPPING_THRESHOLD = 0.3f; const float DEFAULT_AVATAR_MODE_HEIGHT_STEPPING_THRESHOLD = -0.02f; const float DEFAULT_HANDS_VELOCITY_DIRECTION_STEPPING_THRESHOLD = 0.4f; From 0e0966004ce46fa61c4df004c2078de8e809ccd2 Mon Sep 17 00:00:00 2001 From: Ryan Huffman Date: Wed, 25 Jul 2018 14:52:56 -0700 Subject: [PATCH 13/20] Fix edit.js not being able to delete after creating entity This fix puts focus back on the main window when creating an entity so that the user can use shortcuts like 'f' and 'delete' --- scripts/system/edit.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 1c0b7c2dcb..4b8abff84b 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -392,6 +392,8 @@ var toolBar = (function () { entityListTool.sendUpdate(); selectionManager.setSelections([entityID]); + Window.setFocus(); + return entityID; } From 1c1b68ee6633e26a428eeda0211322fbb602e5a4 Mon Sep 17 00:00:00 2001 From: SamGondelman Date: Wed, 25 Jul 2018 19:04:02 -0700 Subject: [PATCH 14/20] emitterShouldTrail fix, review comments, rotateWithEntity --- .../RenderableParticleEffectEntityItem.cpp | 46 +++++++++++-------- .../src/RenderableParticleEffectEntityItem.h | 11 +++-- .../src/textured_particle.slv | 30 +++++++----- .../entities/src/EntityItemProperties.cpp | 23 ++++++++-- libraries/entities/src/EntityItemProperties.h | 3 +- libraries/entities/src/EntityPropertyFlags.h | 1 + .../entities/src/ParticleEffectEntityItem.cpp | 12 +++++ .../entities/src/ParticleEffectEntityItem.h | 6 +++ libraries/gpu/src/gpu/Transform.slh | 2 +- .../particle_explorer/particleExplorer.js | 8 ++++ 10 files changed, 99 insertions(+), 43 deletions(-) diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp index 89c2f0dccf..73f46245c4 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.cpp @@ -101,6 +101,10 @@ void ParticleEffectEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePoi _timeUntilNextEmit = 0; withWriteLock([&]{ _particleProperties = newParticleProperties; + if (!_prevEmitterShouldTrailInitialized) { + _prevEmitterShouldTrailInitialized = true; + _prevEmitterShouldTrail = _particleProperties.emission.shouldTrail; + } }); } _emitting = entity->getIsEmitting(); @@ -149,6 +153,7 @@ void ParticleEffectEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEn particleUniforms.spin.finish = _particleProperties.spin.range.finish; particleUniforms.spin.spread = _particleProperties.spin.gradient.spread; particleUniforms.lifespan = _particleProperties.lifespan; + particleUniforms.rotateWithEntity = _particleProperties.rotateWithEntity ? 1 : 0; }); // Update particle uniforms memcpy(&_uniformBuffer.edit(), &particleUniforms, sizeof(ParticleUniforms)); @@ -180,7 +185,7 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa const auto& azimuthFinish = particleProperties.azimuth.finish; const auto& emitDimensions = particleProperties.emission.dimensions; const auto& emitAcceleration = particleProperties.emission.acceleration.target; - auto emitOrientation = particleProperties.emission.orientation; + auto emitOrientation = baseTransform.getRotation() * particleProperties.emission.orientation; const auto& emitRadiusStart = glm::max(particleProperties.radiusStart, EPSILON); // Avoid math complications at center const auto& emitSpeed = particleProperties.emission.speed.target; const auto& speedSpread = particleProperties.emission.speed.spread; @@ -189,10 +194,9 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa particle.seed = randFloatInRange(-1.0f, 1.0f); particle.expiration = now + (uint64_t)(particleProperties.lifespan * USECS_PER_SECOND); - if (particleProperties.emission.shouldTrail) { - particle.position = baseTransform.getTranslation(); - emitOrientation = baseTransform.getRotation() * emitOrientation; - } + + particle.relativePosition = glm::vec3(0.0f); + particle.basePosition = baseTransform.getTranslation(); // Position, velocity, and acceleration if (polarStart == 0.0f && polarFinish == 0.0f && emitDimensions.z == 0.0f) { @@ -241,7 +245,7 @@ ParticleEffectEntityRenderer::CpuParticle ParticleEffectEntityRenderer::createPa radii.y > 0.0f ? y / (radii.y * radii.y) : 0.0f, radii.z > 0.0f ? z / (radii.z * radii.z) : 0.0f )); - particle.position += emitOrientation * emitPosition; + particle.relativePosition += emitOrientation * emitPosition; } particle.velocity = (emitSpeed + randFloatInRange(-1.0f, 1.0f) * speedSpread) * (emitOrientation * emitDirection); @@ -266,8 +270,8 @@ void ParticleEffectEntityRenderer::stepSimulation() { particleProperties = _particleProperties; }); + const auto& modelTransform = getModelTransform(); if (_emitting && particleProperties.emitting()) { - const auto& modelTransform = getModelTransform(); uint64_t emitInterval = particleProperties.emitIntervalUsecs(); if (emitInterval > 0 && interval >= _timeUntilNextEmit) { auto timeRemaining = interval; @@ -292,15 +296,23 @@ void ParticleEffectEntityRenderer::stepSimulation() { const float deltaTime = (float)interval / (float)USECS_PER_SECOND; // update the particles for (auto& particle : _cpuParticles) { + if (_prevEmitterShouldTrail != particleProperties.emission.shouldTrail) { + if (_prevEmitterShouldTrail) { + particle.relativePosition = particle.relativePosition + particle.basePosition - modelTransform.getTranslation(); + } + particle.basePosition = modelTransform.getTranslation(); + } particle.integrate(deltaTime); } + _prevEmitterShouldTrail = particleProperties.emission.shouldTrail; // Build particle primitives static GpuParticles gpuParticles; gpuParticles.clear(); gpuParticles.reserve(_cpuParticles.size()); // Reserve space - std::transform(_cpuParticles.begin(), _cpuParticles.end(), std::back_inserter(gpuParticles), [](const CpuParticle& particle) { - return GpuParticle(particle.position, glm::vec2(particle.lifetime, particle.seed)); + std::transform(_cpuParticles.begin(), _cpuParticles.end(), std::back_inserter(gpuParticles), [&particleProperties, &modelTransform](const CpuParticle& particle) { + glm::vec3 position = particle.relativePosition + (particleProperties.emission.shouldTrail ? particle.basePosition : modelTransform.getTranslation()); + return GpuParticle(position, glm::vec2(particle.lifetime, particle.seed)); }); // Update particle buffer @@ -328,15 +340,11 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { } Transform transform; - // In trail mode, the particles are created in world space. - // so we only set a transform if they're not in trail mode - if (!_particleProperties.emission.shouldTrail) { - - withReadLock([&] { - transform = _renderTransform; - }); - transform.setScale(vec3(1)); - } + // The particles are in world space, so the transform is unused, except for the rotation, which we use + // if the particles are marked rotateWithEntity + withReadLock([&] { + transform.setRotation(_renderTransform.getRotation()); + }); batch.setModelTransform(transform); batch.setUniformBuffer(PARTICLE_UNIFORM_SLOT, _uniformBuffer); batch.setInputFormat(_vertexFormat); @@ -345,5 +353,3 @@ void ParticleEffectEntityRenderer::doRender(RenderArgs* args) { auto numParticles = _particleBuffer->getSize() / sizeof(GpuParticle); batch.drawInstanced((gpu::uint32)numParticles, gpu::TRIANGLE_STRIP, (gpu::uint32)VERTEX_PER_PARTICLE); } - - diff --git a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h index e1e3cd210e..7655918c58 100644 --- a/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h +++ b/libraries/entities-renderer/src/RenderableParticleEffectEntityItem.h @@ -49,13 +49,14 @@ private: float seed { 0.0f }; uint64_t expiration { 0 }; float lifetime { 0.0f }; - glm::vec3 position; + glm::vec3 basePosition; + glm::vec3 relativePosition; glm::vec3 velocity; glm::vec3 acceleration; void integrate(float deltaTime) { glm::vec3 atSquared = (0.5f * deltaTime * deltaTime) * acceleration; - position += velocity * deltaTime + atSquared; + relativePosition += velocity * deltaTime + atSquared; velocity += acceleration * deltaTime; lifetime += deltaTime; } @@ -76,14 +77,16 @@ private: InterpolationData color; // rgba InterpolationData spin; float lifespan; - glm::vec3 spare; + int rotateWithEntity; + glm::vec2 spare; }; - static CpuParticle createParticle(uint64_t now, const Transform& baseTransform, const particle::Properties& particleProperties); void stepSimulation(); particle::Properties _particleProperties; + bool _prevEmitterShouldTrail; + bool _prevEmitterShouldTrailInitialized { false }; CpuParticles _cpuParticles; bool _emitting { false }; uint64_t _timeUntilNextEmit { 0 }; diff --git a/libraries/entities-renderer/src/textured_particle.slv b/libraries/entities-renderer/src/textured_particle.slv index bc3ef4fbb0..22254c0ab0 100644 --- a/libraries/entities-renderer/src/textured_particle.slv +++ b/libraries/entities-renderer/src/textured_particle.slv @@ -38,7 +38,9 @@ struct ParticleUniforms { Radii radius; Colors color; Spin spin; - vec4 lifespan; // x is lifespan, 3 spare floats + float lifespan; + int rotateWithEntity; + vec2 spare; }; layout(std140) uniform particleBuffer { @@ -120,7 +122,7 @@ void main(void) { int twoTriID = gl_VertexID - particleID * NUM_VERTICES_PER_PARTICLE; // Particle properties - float age = inColor.x / particle.lifespan.x; + float age = inColor.x / particle.lifespan; float seed = inColor.y; // Pass the texcoord @@ -140,20 +142,24 @@ void main(void) { float radiusSpread = 2.0 * hifi_hash(seed * 6.0) - 1.0; radius = max(radius + radiusSpread * particle.radius.spread, 0.0); - vec4 anchorPoint; - vec4 _inPosition = vec4(inPosition, 1.0); - <$transformModelToEyePos(cam, obj, _inPosition, anchorPoint)$> + // inPosition is in world space + vec4 anchorPoint = cam._view * vec4(inPosition, 1.0); mat3 view3 = mat3(cam._view); - vec3 worldUpEye = normalize(view3 * vec3(0, 1, 0)); - vec3 right = cross(vec3(0, 0, -1), worldUpEye); - vec3 up = cross(right, vec3(0, 0, -1)); + vec3 UP = vec3(0, 1, 0); + vec3 modelUpWorld; + <$transformModelToWorldDir(cam, obj, UP, modelUpWorld)$> + vec3 upWorld = mix(UP, normalize(modelUpWorld), particle.rotateWithEntity); + vec3 upEye = normalize(view3 * upWorld); + vec3 FORWARD = vec3(0, 0, -1); + vec3 particleRight = normalize(cross(FORWARD, upEye)); + vec3 particleUp = cross(particleRight, FORWARD); // don't need to normalize // This ordering ensures that un-rotated particles render upright in the viewer. vec3 UNIT_QUAD[NUM_VERTICES_PER_PARTICLE] = vec3[NUM_VERTICES_PER_PARTICLE]( - normalize(-right + up), - normalize(-right - up), - normalize(right + up), - normalize(right - up) + normalize(-particleRight + particleUp), + normalize(-particleRight - particleUp), + normalize(particleRight + particleUp), + normalize(particleRight - particleUp) ); float c = cos(spin); float s = sin(spin); diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index f86c7a18b7..2d0fcd0496 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -373,6 +373,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { CHECK_PROPERTY_CHANGE(PROP_SPIN_SPREAD, spinSpread); CHECK_PROPERTY_CHANGE(PROP_SPIN_START, spinStart); CHECK_PROPERTY_CHANGE(PROP_SPIN_FINISH, spinFinish); + CHECK_PROPERTY_CHANGE(PROP_PARTICLE_ROTATE_WITH_ENTITY, rotateWithEntity); // Certifiable Properties CHECK_PROPERTY_CHANGE(PROP_ITEM_NAME, itemName); @@ -913,12 +914,14 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const { * @property {number} alphaSpread=0 - The spread in alpha that each particle is given. If alpha == 0.5 * and alphaSpread == 0.25, each particle will have an alpha in the range 0.250.75. * @property {number} particleSpin=0 - The spin of each particle at the middle of its life. In the range -2*PI2*PI. - * @property {number} spinStart=null - The spin of each particle at the start of its life. In the range -2*PI2*PI. - * If null, the particleSpin value is used. - * @property {number} spinFinish=null - The spin of each particle at the end of its life. In the range -2*PI2*PI. - * If null, the particleSpin value is used. + * @property {number} spinStart=NaN - The spin of each particle at the start of its life. In the range -2*PI2*PI. + * If NaN, the particleSpin value is used. + * @property {number} spinFinish=NaN - The spin of each particle at the end of its life. In the range -2*PI2*PI. + * If NaN, the particleSpin value is used. * @property {number} spinSpread=0 - The spread in spin that each particle is given. In the range 02*PI. If particleSpin == PI * and spinSpread == PI/2, each particle will have a spin in the range PI/23*PI/2. + * @property {boolean} rotateWithEntity=false - Whether or not the particles' spin will rotate with the entity. If false, when particleSpin == 0, the particles will point + * up in the world. If true, they will point towards the entity's up vector, based on its orientation. * * @property {ShapeType} shapeType="none" - Currently not used. Read-only. * @@ -1306,6 +1309,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_SPREAD, spinSpread); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_START, spinStart); COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_SPIN_FINISH, spinFinish); + COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_PARTICLE_ROTATE_WITH_ENTITY, rotateWithEntity); } // Models only @@ -1602,6 +1606,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(spinSpread, float, setSpinSpread); COPY_PROPERTY_FROM_QSCRIPTVALUE(spinStart, float, setSpinStart); COPY_PROPERTY_FROM_QSCRIPTVALUE(spinFinish, float, setSpinFinish); + COPY_PROPERTY_FROM_QSCRIPTVALUE(rotateWithEntity, bool, setRotateWithEntity); // Certifiable Properties COPY_PROPERTY_FROM_QSCRIPTVALUE(itemName, QString, setItemName); @@ -1774,6 +1779,7 @@ void EntityItemProperties::merge(const EntityItemProperties& other) { COPY_PROPERTY_IF_CHANGED(spinSpread); COPY_PROPERTY_IF_CHANGED(spinStart); COPY_PROPERTY_IF_CHANGED(spinFinish); + COPY_PROPERTY_IF_CHANGED(rotateWithEntity); // Certifiable Properties COPY_PROPERTY_IF_CHANGED(itemName); @@ -1991,6 +1997,7 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue ADD_PROPERTY_TO_MAP(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float); ADD_PROPERTY_TO_MAP(PROP_SPIN_START, SpinStart, spinStart, float); ADD_PROPERTY_TO_MAP(PROP_SPIN_FINISH, SpinFinish, spinFinish, float); + ADD_PROPERTY_TO_MAP(PROP_PARTICLE_ROTATE_WITH_ENTITY, RotateWithEntity, rotateWithEntity, float); // Certifiable Properties ADD_PROPERTY_TO_MAP(PROP_ITEM_NAME, ItemName, itemName, QString); @@ -2324,6 +2331,7 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, properties.getSpinSpread()); APPEND_ENTITY_PROPERTY(PROP_SPIN_START, properties.getSpinStart()); APPEND_ENTITY_PROPERTY(PROP_SPIN_FINISH, properties.getSpinFinish()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, properties.getRotateWithEntity()) } if (properties.getType() == EntityTypes::Zone) { @@ -2703,6 +2711,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_SPREAD, float, setSpinSpread); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_START, float, setSpinStart); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SPIN_FINISH, float, setSpinFinish); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_PARTICLE_ROTATE_WITH_ENTITY, bool, setRotateWithEntity); } if (properties.getType() == EntityTypes::Zone) { @@ -2972,7 +2981,7 @@ void EntityItemProperties::markAllChanged() { _shapeTypeChanged = true; _isEmittingChanged = true; - _emitterShouldTrail = true; + _emitterShouldTrailChanged = true; _maxParticlesChanged = true; _lifespanChanged = true; _emitRateChanged = true; @@ -3001,6 +3010,7 @@ void EntityItemProperties::markAllChanged() { _spinStartChanged = true; _spinFinishChanged = true; _spinSpreadChanged = true; + _rotateWithEntityChanged = true; _materialURLChanged = true; _materialMappingModeChanged = true; @@ -3361,6 +3371,9 @@ QList EntityItemProperties::listChangedProperties() { if (spinFinishChanged()) { out += "spinFinish"; } + if (rotateWithEntityChanged()) { + out += "rotateWithEntity"; + } if (materialURLChanged()) { out += "materialURL"; } diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index 7799d45b22..04e54c54a5 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -238,7 +238,8 @@ public: DEFINE_PROPERTY(PROP_PARTICLE_SPIN, ParticleSpin, particleSpin, float, particle::DEFAULT_PARTICLE_SPIN); DEFINE_PROPERTY(PROP_SPIN_SPREAD, SpinSpread, spinSpread, float, particle::DEFAULT_SPIN_SPREAD); DEFINE_PROPERTY(PROP_SPIN_START, SpinStart, spinStart, float, particle::DEFAULT_SPIN_START); - DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH) + DEFINE_PROPERTY(PROP_SPIN_FINISH, SpinFinish, spinFinish, float, particle::DEFAULT_SPIN_FINISH); + DEFINE_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, RotateWithEntity, rotateWithEntity, bool, particle::DEFAULT_ROTATE_WITH_ENTITY); // Certifiable Properties - related to Proof of Purchase certificates DEFINE_PROPERTY_REF(PROP_ITEM_NAME, ItemName, itemName, QString, ENTITY_ITEM_DEFAULT_ITEM_NAME); diff --git a/libraries/entities/src/EntityPropertyFlags.h b/libraries/entities/src/EntityPropertyFlags.h index bece248fe7..156c5d9dd4 100644 --- a/libraries/entities/src/EntityPropertyFlags.h +++ b/libraries/entities/src/EntityPropertyFlags.h @@ -255,6 +255,7 @@ enum EntityPropertyList { PROP_SPIN_START, PROP_SPIN_FINISH, PROP_SPIN_SPREAD, + PROP_PARTICLE_ROTATE_WITH_ENTITY, //////////////////////////////////////////////////////////////////////////////////////////////////// // ATTENTION: add new properties to end of list just ABOVE this line diff --git a/libraries/entities/src/ParticleEffectEntityItem.cpp b/libraries/entities/src/ParticleEffectEntityItem.cpp index c1785639e0..238f41b05f 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.cpp +++ b/libraries/entities/src/ParticleEffectEntityItem.cpp @@ -92,6 +92,7 @@ bool operator==(const Properties& a, const Properties& b) { (a.alpha == b.alpha) && (a.radius == b.radius) && (a.spin == b.spin) && + (a.rotateWithEntity == b.rotateWithEntity) && (a.radiusStart == b.radiusStart) && (a.lifespan == b.lifespan) && (a.maxParticles == b.maxParticles) && @@ -444,6 +445,7 @@ EntityItemProperties ParticleEffectEntityItem::getProperties(EntityPropertyFlags COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinSpread, getSpinSpread); COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinStart, getSpinStart); COPY_ENTITY_PROPERTY_TO_PROPERTIES(spinFinish, getSpinFinish); + COPY_ENTITY_PROPERTY_TO_PROPERTIES(rotateWithEntity, getRotateWithEntity); return properties; } @@ -485,6 +487,7 @@ bool ParticleEffectEntityItem::setProperties(const EntityItemProperties& propert SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinSpread, setSpinSpread); SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinStart, setSpinStart); SET_ENTITY_PROPERTY_FROM_PROPERTIES(spinFinish, setSpinFinish); + SET_ENTITY_PROPERTY_FROM_PROPERTIES(rotateWithEntity, setRotateWithEntity); if (somethingChanged) { bool wantDebug = false; @@ -569,6 +572,7 @@ int ParticleEffectEntityItem::readEntitySubclassDataFromBuffer(const unsigned ch READ_ENTITY_PROPERTY(PROP_SPIN_SPREAD, float, setSpinSpread); READ_ENTITY_PROPERTY(PROP_SPIN_START, float, setSpinStart); READ_ENTITY_PROPERTY(PROP_SPIN_FINISH, float, setSpinFinish); + READ_ENTITY_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, bool, setRotateWithEntity); return bytesRead; } @@ -610,6 +614,7 @@ EntityPropertyFlags ParticleEffectEntityItem::getEntityProperties(EncodeBitstrea requestedProperties += PROP_SPIN_SPREAD; requestedProperties += PROP_SPIN_START; requestedProperties += PROP_SPIN_FINISH; + requestedProperties += PROP_PARTICLE_ROTATE_WITH_ENTITY; return requestedProperties; } @@ -657,6 +662,7 @@ void ParticleEffectEntityItem::appendSubclassData(OctreePacketData* packetData, APPEND_ENTITY_PROPERTY(PROP_SPIN_SPREAD, getSpinSpread()); APPEND_ENTITY_PROPERTY(PROP_SPIN_START, getSpinStart()); APPEND_ENTITY_PROPERTY(PROP_SPIN_FINISH, getSpinFinish()); + APPEND_ENTITY_PROPERTY(PROP_PARTICLE_ROTATE_WITH_ENTITY, getRotateWithEntity()); } @@ -728,6 +734,12 @@ void ParticleEffectEntityItem::setEmitterShouldTrail(bool emitterShouldTrail) { }); } +void ParticleEffectEntityItem::setRotateWithEntity(bool rotateWithEntity) { + withWriteLock([&] { + _particleProperties.rotateWithEntity = rotateWithEntity; + }); +} + particle::Properties ParticleEffectEntityItem::getParticleProperties() const { particle::Properties result; withReadLock([&] { diff --git a/libraries/entities/src/ParticleEffectEntityItem.h b/libraries/entities/src/ParticleEffectEntityItem.h index e4120eed63..480b78ffcc 100644 --- a/libraries/entities/src/ParticleEffectEntityItem.h +++ b/libraries/entities/src/ParticleEffectEntityItem.h @@ -77,6 +77,7 @@ namespace particle { static const float MAXIMUM_PARTICLE_SPIN = 2.0f * SCRIPT_MAXIMUM_PI; static const QString DEFAULT_TEXTURES = ""; static const bool DEFAULT_EMITTER_SHOULD_TRAIL = false; + static const bool DEFAULT_ROTATE_WITH_ENTITY = false; template struct Range { @@ -158,6 +159,7 @@ namespace particle { float radiusStart { DEFAULT_EMIT_RADIUS_START }; RangeGradient radius { DEFAULT_PARTICLE_RADIUS, DEFAULT_RADIUS_START, DEFAULT_RADIUS_FINISH, DEFAULT_RADIUS_SPREAD }; RangeGradient spin { DEFAULT_PARTICLE_SPIN, DEFAULT_SPIN_START, DEFAULT_SPIN_FINISH, DEFAULT_SPIN_SPREAD }; + bool rotateWithEntity { DEFAULT_ROTATE_WITH_ENTITY }; float lifespan { DEFAULT_LIFESPAN }; uint32_t maxParticles { DEFAULT_MAX_PARTICLES }; EmitProperties emission; @@ -176,6 +178,7 @@ namespace particle { color = other.color; alpha = other.alpha; spin = other.spin; + rotateWithEntity = other.rotateWithEntity; radius = other.radius; lifespan = other.lifespan; maxParticles = other.maxParticles; @@ -326,6 +329,9 @@ public: void setSpinSpread(float spinSpread); float getSpinSpread() const { return _particleProperties.spin.gradient.spread; } + void setRotateWithEntity(bool rotateWithEntity); + bool getRotateWithEntity() const { return _particleProperties.rotateWithEntity; } + void computeAndUpdateDimensions(); void setTextures(const QString& textures); diff --git a/libraries/gpu/src/gpu/Transform.slh b/libraries/gpu/src/gpu/Transform.slh index 50c0bc13ed..864a106350 100644 --- a/libraries/gpu/src/gpu/Transform.slh +++ b/libraries/gpu/src/gpu/Transform.slh @@ -238,7 +238,7 @@ TransformObject getTransformObject() { <@endfunc@> <@func transformModelToWorldDir(cameraTransform, objectTransform, modelDir, worldDir)@> - { // transformModelToEyeDir + { // transformModelToWorldDir vec3 mr0 = <$objectTransform$>._modelInverse[0].xyz; vec3 mr1 = <$objectTransform$>._modelInverse[1].xyz; vec3 mr2 = <$objectTransform$>._modelInverse[2].xyz; diff --git a/scripts/system/particle_explorer/particleExplorer.js b/scripts/system/particle_explorer/particleExplorer.js index a6cbbc14cb..f1b7c8600f 100644 --- a/scripts/system/particle_explorer/particleExplorer.js +++ b/scripts/system/particle_explorer/particleExplorer.js @@ -398,6 +398,14 @@ min: -360.0, max: 360.0 }, + { + type: "Row" + }, + { + id: "rotateWithEntity", + name: "Rotate with Entity", + type: "Boolean" + }, { type: "Row" } From 12cb212dc73a6b2c6f0426f12312e75dc7257081 Mon Sep 17 00:00:00 2001 From: amantley Date: Thu, 26 Jul 2018 12:05:01 -0700 Subject: [PATCH 15/20] used avatar constants from AvatarConstants.h to initialize tpposehips and tposerightfoot, and added space between multiplication to meet coding standards --- interface/src/avatar/MyAvatar.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c9e268f418..961c99696e 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -3060,8 +3060,8 @@ glm::vec3 MyAvatar::computeCounterBalance() { JointMass cgLeftHandMass(QString("LeftHand"), DEFAULT_AVATAR_LEFTHAND_MASS, glm::vec3(0.0f, 0.0f, 0.0f)); JointMass cgRightHandMass(QString("RightHand"), DEFAULT_AVATAR_RIGHTHAND_MASS, glm::vec3(0.0f, 0.0f, 0.0f)); glm::vec3 tposeHead = DEFAULT_AVATAR_HEAD_POS; - glm::vec3 tposeHips = glm::vec3(0.0f, 0.0f, 0.0f); - glm::vec3 tposeRightFoot = glm::vec3(0.0f, -1.0f, 0.0f); + glm::vec3 tposeHips = DEFAULT_AVATAR_HIPS_POS; + glm::vec3 tposeRightFoot = DEFAULT_AVATAR_RIGHTFOOT_POS; if (_skeletonModel->getRig().indexOfJoint(cgHeadMass.name) != -1) { cgHeadMass.position = getAbsoluteJointTranslationInObjectFrame(_skeletonModel->getRig().indexOfJoint(cgHeadMass.name)); @@ -3107,8 +3107,8 @@ glm::vec3 MyAvatar::computeCounterBalance() { glm::vec3 xzDiff((cgHeadMass.position.x - counterBalancedCg.x), 0.0f, (cgHeadMass.position.z - counterBalancedCg.z)); float headMinusHipXz = glm::length(xzDiff); float headHipDefault = glm::length(tposeHead - tposeHips); - float hipFootDefault = glm::length(tposeHips - tposeRightFoot); - float sitSquatThreshold = tposeHips.y - (UPPER_LEG_FRACTION*hipFootDefault); + float hipFootDefault = tposeHips.y - tposeRightFoot.y; + float sitSquatThreshold = tposeHips.y - (UPPER_LEG_FRACTION * hipFootDefault); float hipHeight = 0.0f; if (headHipDefault > headMinusHipXz) { hipHeight = sqrtf((headHipDefault * headHipDefault) - (headMinusHipXz * headMinusHipXz)); From f8c611b1d07bd4eb27a9c772e27f55997872bd99 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 26 Jul 2018 15:35:12 -0700 Subject: [PATCH 16/20] Divorce HMD and Desktop flying settings, implement setters and getters, change loadData and saveData in MyAvatar.cpp --- interface/src/Application.cpp | 6 --- interface/src/avatar/MyAvatar.cpp | 51 ++++++++++++++++++++++++-- interface/src/avatar/MyAvatar.h | 26 +++++++++++++ interface/src/ui/PreferencesDialog.cpp | 4 +- 4 files changed, 76 insertions(+), 11 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6963f945aa..6550f5da40 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4844,12 +4844,6 @@ void Application::loadSettings() { isFirstPerson = (qApp->isHMDMode()); - // Flying should be disabled by default in HMD mode on first run, and it - // should be enabled by default in desktop mode. - - auto myAvatar = getMyAvatar(); - myAvatar->setFlyingEnabled(!isFirstPerson); - } else { // if this is not the first run, the camera will be initialized differently depending on user settings diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index bf7276d5d5..70619c452f 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -577,9 +577,11 @@ void MyAvatar::updateChildCauterization(SpatiallyNestablePointer object, bool ca void MyAvatar::simulate(float deltaTime) { PerformanceTimer perfTimer("simulate"); - + animateScaleChanges(deltaTime); + setFlyingEnabled(getFlyingEnabled()); + if (_cauterizationNeedsUpdate) { _cauterizationNeedsUpdate = false; @@ -1131,6 +1133,8 @@ void MyAvatar::saveData() { settings.setValue("collisionSoundURL", _collisionSoundURL); settings.setValue("useSnapTurn", _useSnapTurn); settings.setValue("userHeight", getUserHeight()); + settings.setValue("flyingDesktop", getFlyingDesktopPref()); + settings.setValue("flyingHMD", getFlyingHMDPref()); settings.setValue("enabledFlying", getFlyingEnabled()); settings.endGroup(); @@ -1281,8 +1285,13 @@ void MyAvatar::loadData() { settings.remove("avatarEntityData"); } setAvatarEntityDataChanged(true); + + // Flying preferences must be loaded before calling setFlyingEnabled() Setting::Handle firstRunVal { Settings::firstRun, true }; - setFlyingEnabled(firstRunVal.get() ? getFlyingEnabled() : settings.value("enabledFlying").toBool()); + setFlyingDesktopPref(firstRunVal.get() ? true : settings.value("flyingDesktop").toBool()); + setFlyingHMDPref(firstRunVal.get() ? false : settings.value("flyingHMD").toBool()); + setFlyingEnabled(getFlyingEnabled()); + setDisplayName(settings.value("displayName").toString()); setCollisionSoundURL(settings.value("collisionSoundURL", DEFAULT_AVATAR_COLLISION_SOUND_URL).toString()); setSnapTurn(settings.value("useSnapTurn", _useSnapTurn).toBool()); @@ -2825,6 +2834,12 @@ void MyAvatar::setFlyingEnabled(bool enabled) { return; } + if (qApp->isHMDMode()) { + setFlyingHMDPref(enabled); + } else { + setFlyingDesktopPref(enabled); + } + _enableFlying = enabled; } @@ -2840,7 +2855,37 @@ bool MyAvatar::isInAir() { bool MyAvatar::getFlyingEnabled() { // May return true even if client is not allowed to fly in the zone. - return _enableFlying; + return (qApp->isHMDMode() ? getFlyingHMDPref() : getFlyingDesktopPref()); +} + +void MyAvatar::setFlyingDesktopPref(bool enabled) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setFlyingDesktopPref", Q_ARG(bool, enabled)); + return; + } + + //if (!(qApp->isHMDMode())) { _enableFlying = enabled; } + + _flyingPrefDesktop = enabled; +} + +bool MyAvatar::getFlyingDesktopPref() { + return _flyingPrefDesktop; +} + +void MyAvatar::setFlyingHMDPref(bool enabled) { + if (QThread::currentThread() != thread()) { + QMetaObject::invokeMethod(this, "setFlyingHMDPref", Q_ARG(bool, enabled)); + return; + } + + //if ((qApp->isHMDMode())) { _enableFlying = enabled; } + + _flyingPrefHMD = enabled; +} + +bool MyAvatar::getFlyingHMDPref() { + return _flyingPrefHMD; } // Public interface for targetscale diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index add00962da..0f2f09e1cf 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -953,6 +953,30 @@ public: */ Q_INVOKABLE bool getFlyingEnabled(); + /**jsdoc + * @function MyAvatar.setFlyingDesktopPref + * @param {boolean} enabled + */ + Q_INVOKABLE void setFlyingDesktopPref(bool enabled); + + /**jsdoc + * @function MyAvatar.getFlyingDesktopPref + * @returns {boolean} + */ + Q_INVOKABLE bool getFlyingDesktopPref(); + + /**jsdoc + * @function MyAvatar.setFlyingDesktopPref + * @param {boolean} enabled + */ + Q_INVOKABLE void setFlyingHMDPref(bool enabled); + + /**jsdoc + * @function MyAvatar.getFlyingDesktopPref + * @returns {boolean} + */ + Q_INVOKABLE bool getFlyingHMDPref(); + /**jsdoc * @function MyAvatar.getAvatarScale @@ -1503,6 +1527,8 @@ private: std::bitset _disabledDriveKeys; bool _enableFlying { false }; + bool _flyingPrefDesktop { true }; + bool _flyingPrefHMD { false }; bool _wasPushing { false }; bool _isPushing { false }; bool _isBeingPushed { false }; diff --git a/interface/src/ui/PreferencesDialog.cpp b/interface/src/ui/PreferencesDialog.cpp index 135b59a152..50a4d17cae 100644 --- a/interface/src/ui/PreferencesDialog.cpp +++ b/interface/src/ui/PreferencesDialog.cpp @@ -313,8 +313,8 @@ void setupPreferences() { getter, setter)); } { - auto getter = [=]()->bool { return myAvatar->getFlyingEnabled(); }; - auto setter = [=](bool value) { myAvatar->setFlyingEnabled(value); }; + auto getter = [=]()->bool { return myAvatar->getFlyingHMDPref(); }; + auto setter = [=](bool value) { myAvatar->setFlyingHMDPref(value); }; preferences->addPreference(new CheckPreference(VR_MOVEMENT, "Flying & jumping", getter, setter)); } { From f3d0d9b4a04f3804a219d85bdd653eaafb5aa691 Mon Sep 17 00:00:00 2001 From: r3tk0n Date: Thu, 26 Jul 2018 15:37:42 -0700 Subject: [PATCH 17/20] Clean up garbage comments. --- interface/src/avatar/MyAvatar.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 70619c452f..077ab24653 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -2864,8 +2864,6 @@ void MyAvatar::setFlyingDesktopPref(bool enabled) { return; } - //if (!(qApp->isHMDMode())) { _enableFlying = enabled; } - _flyingPrefDesktop = enabled; } @@ -2879,8 +2877,6 @@ void MyAvatar::setFlyingHMDPref(bool enabled) { return; } - //if ((qApp->isHMDMode())) { _enableFlying = enabled; } - _flyingPrefHMD = enabled; } From 3bfdd3ff5842021567a0209c96bc21c1998b3ec4 Mon Sep 17 00:00:00 2001 From: David Rowe Date: Fri, 27 Jul 2018 15:18:40 +1200 Subject: [PATCH 18/20] Maintain virtual and real world orientations when teleport --- scripts/system/controllers/controllerModules/teleport.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/system/controllers/controllerModules/teleport.js b/scripts/system/controllers/controllerModules/teleport.js index 3bf99ca26a..6564c91d8a 100644 --- a/scripts/system/controllers/controllerModules/teleport.js +++ b/scripts/system/controllers/controllerModules/teleport.js @@ -325,7 +325,7 @@ Script.include("/~/system/libraries/controllers.js"); } else if (target === TARGET.SURFACE) { var offset = getAvatarFootOffset(); result.intersection.y += offset; - MyAvatar.goToLocation(result.intersection, false, {x: 0, y: 0, z: 0, w: 1}, false); + MyAvatar.goToLocation(result.intersection, true, HMD.orientation, false); HMD.centerUI(); MyAvatar.centerBody(); } From cf04a91a83ccba89ed52b14f854eacb76a45565e Mon Sep 17 00:00:00 2001 From: Andrew Meadows Date: Fri, 27 Jul 2018 09:02:19 -0700 Subject: [PATCH 19/20] use smaller CCD spheres for thin objects --- libraries/physics/src/ObjectMotionState.cpp | 41 +++++++++++---------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/libraries/physics/src/ObjectMotionState.cpp b/libraries/physics/src/ObjectMotionState.cpp index 0e6eb2511d..310cf7cec1 100644 --- a/libraries/physics/src/ObjectMotionState.cpp +++ b/libraries/physics/src/ObjectMotionState.cpp @@ -155,26 +155,25 @@ void ObjectMotionState::setMotionType(PhysicsMotionType motionType) { // Update the Continuous Collision Detection (CCD) configuration settings of our RigidBody so that // CCD will be enabled automatically when its speed surpasses a certain threshold. void ObjectMotionState::updateCCDConfiguration() { - if (_body) { - if (_shape) { - // If this object moves faster than its bounding radius * RADIUS_MOTION_THRESHOLD_MULTIPLIER, - // CCD will be enabled for this object. - const auto RADIUS_MOTION_THRESHOLD_MULTIPLIER = 0.5f; + assert(_body); + if (_shape && _shape->getShapeType() != TRIANGLE_MESH_SHAPE_PROXYTYPE) { + // find minumum dimension of shape + btVector3 aabbMin, aabbMax; + btTransform transform; + transform.setIdentity(); + _shape->getAabb(transform, aabbMin, aabbMax); + aabbMin = aabbMax - aabbMin; + btScalar radius = *((btScalar*)(aabbMin) + aabbMin.minAxis()); - btVector3 center; - btScalar radius; - _shape->getBoundingSphere(center, radius); - _body->setCcdMotionThreshold(radius * RADIUS_MOTION_THRESHOLD_MULTIPLIER); + // use the minimum dimension as the radius of the CCD proxy sphere + _body->setCcdSweptSphereRadius(radius); - // TODO: Ideally the swept sphere radius would be contained by the object. Using the bounding sphere - // radius works well for spherical objects, but may cause issues with other shapes. For arbitrary - // objects we may want to consider a different approach, such as grouping rigid bodies together. - - _body->setCcdSweptSphereRadius(radius); - } else { - // Disable CCD - _body->setCcdMotionThreshold(0); - } + // also use the radius as the motion threshold for enabling CCD + _body->setCcdMotionThreshold(radius); + } else { + // disable CCD + _body->setCcdSweptSphereRadius(0.0f); + _body->setCcdMotionThreshold(0.0f); } } @@ -188,8 +187,8 @@ void ObjectMotionState::setRigidBody(btRigidBody* body) { if (_body) { _body->setUserPointer(this); assert(_body->getCollisionShape() == _shape); + updateCCDConfiguration(); } - updateCCDConfiguration(); } } @@ -199,6 +198,9 @@ void ObjectMotionState::setShape(const btCollisionShape* shape) { getShapeManager()->releaseShape(_shape); } _shape = shape; + if (_body) { + updateCCDConfiguration(); + } } } @@ -312,7 +314,6 @@ bool ObjectMotionState::handleHardAndEasyChanges(uint32_t& flags, PhysicsEngine* } else { _body->setCollisionShape(const_cast(newShape)); setShape(newShape); - updateCCDConfiguration(); } } if (flags & EASY_DIRTY_PHYSICS_FLAGS) { From 91d509f5a45a70739e0b62b5f849d96b738af541 Mon Sep 17 00:00:00 2001 From: Seth Alves Date: Fri, 27 Jul 2018 10:35:26 -0700 Subject: [PATCH 20/20] fix a crash when grabbing a non-dynamic entity with an overlay child --- interface/src/avatar/MyAvatar.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 077ab24653..7534ff1c33 100755 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -726,16 +726,18 @@ void MyAvatar::simulate(float deltaTime) { properties.setQueryAACubeDirty(); properties.setLastEdited(now); - packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, entity->getID(), properties); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, + entity->getID(), properties); entity->setLastBroadcast(usecTimestampNow()); entity->forEachDescendant([&](SpatiallyNestablePointer descendant) { - EntityItemPointer entityDescendant = std::static_pointer_cast(descendant); - if (!entityDescendant->getClientOnly() && descendant->updateQueryAACube()) { + EntityItemPointer entityDescendant = std::dynamic_pointer_cast(descendant); + if (entityDescendant && !entityDescendant->getClientOnly() && descendant->updateQueryAACube()) { EntityItemProperties descendantProperties; descendantProperties.setQueryAACube(descendant->getQueryAACube()); descendantProperties.setLastEdited(now); - packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, entityDescendant->getID(), descendantProperties); + packetSender->queueEditEntityMessage(PacketType::EntityEdit, entityTree, + entityDescendant->getID(), descendantProperties); entityDescendant->setLastBroadcast(now); // for debug/physics status icons } });