diff --git a/android/build.gradle b/android/build.gradle index 1dfef97f91..3719e548bc 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -66,17 +66,17 @@ ext { def baseFolder = new File(HIFI_ANDROID_PRECOMPILED) def appDir = new File(projectDir, 'app') def jniFolder = new File(appDir, 'src/main/jniLibs/arm64-v8a') -def baseUrl = 'https://hifi-public.s3.amazonaws.com/austin/android/' +def baseUrl = '' -def qtFile='qt-5.9.3_linux_armv8-libcpp_openssl.tgz' +def qtFile='https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_linux_armv8-libcpp_openssl.tgz' def qtChecksum='04599670ccca84bd2b15f6915568eb2d' def qtVersionId='PeoqzN31n.YvLfs9JE2SgHgZ4.IaKAlt' if (Os.isFamily(Os.FAMILY_MAC)) { - qtFile = 'qt-5.9.3_osx_armv8-libcpp_openssl.tgz' + qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_osx_armv8-libcpp_openssl.tgz' qtChecksum='4b02de9d67d6bfb202355a808d2d9c59' qtVersionId='HygCmtMLPYioyil0DfXckGVzhw2SXZA9' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - qtFile = 'qt-5.9.3_win_armv8-libcpp_openssl.tgz' + qtFile = 'https://hifi-public.s3.amazonaws.com/austin/android/qt-5.9.3_win_armv8-libcpp_openssl.tgz' qtChecksum='c3e25db64002d0f43cf565e0ef708911' qtVersionId='HeVObSVLCBoc7yY7He1oBMvPIH0VkClT' } @@ -88,58 +88,58 @@ def packages = [ checksum: qtChecksum, ], bullet: [ - file: 'bullet-2.83_armv8-libcpp.tgz', - versionId: 'ljb7v.1IjVRqyopUKVDbVnLA4z88J8Eo', - checksum: '2c558d604fce337f5eba3eb7ec1252fd', + file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/bullet-2.88_armv8-libcpp.tgz', + versionId: 'S8YaoED0Cl8sSb8fSV7Q2G1lQJSNDxqg', + checksum: '81642779ccb110f8c7338e8739ac38a0', ], draco: [ - file: 'draco_armv8-libcpp.tgz', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/draco_armv8-libcpp.tgz', versionId: 'cA3tVJSmkvb1naA3l6D_Jv2Noh.4yc4m', checksum: '617a80d213a5ec69fbfa21a1f2f738cd', ], glad: [ - file: 'glad_armv8-libcpp.zip', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/glad_armv8-libcpp.zip', versionId: 'Q9szthzeye8fFyAA.cY26Lgn2B8kezEE', checksum: 'a8ee8584cf1ccd34766c7ddd9d5e5449', ], glm: [ - file: 'glm-0.9.8.tgz', - versionId: 'BlkJNwaYV2Gfy5XwMeU7K0uzPDRKFMt2', - checksum: 'd2b42cee31d2bc17bab6ce69e6b3f30a', + file: 'https://hifi-public.s3.amazonaws.com/dependencies/android/glm-0.9.8.5-patched.tgz', + versionId: 'cskfMoJrFlAeqI3WPxemyO_Cxt7rT9EJ', + checksum: '067b5fe16b220b5b1a1039ba51b062ae', ], gvr: [ - file: 'gvrsdk_v1.101.0.tgz', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/gvrsdk_v1.101.0.tgz', versionId: 'UTberAIFraEfF9IVjoV66u1DTPTopgeY', checksum: '57fd02baa069176ba18597a29b6b4fc7', ], nvtt: [ - file: 'nvtt_armv8-libcpp.zip', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/nvtt_armv8-libcpp.zip', versionId: 'vLqrqThvpq4gp75BHMAqO6HhfTXaa0An', checksum: 'eb46d0b683e66987190ed124aabf8910', sharedLibFolder: 'lib', includeLibs: ['libnvtt.so', 'libnvmath.so', 'libnvimage.so', 'libnvcore.so'], ], openssl: [ - file: 'openssl-1.1.0g_armv8.tgz', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/openssl-1.1.0g_armv8.tgz', versionId: 'DmahmSGFS4ltpHyTdyQvv35WOeUOiib9', checksum: 'cabb681fbccd79594f65fcc266e02f32', ], polyvox: [ - file: 'polyvox_armv8-libcpp.tgz', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/polyvox_armv8-libcpp.tgz', versionId: 'LDJtzMTvdm4SAc2KYg8Cg6uwWk4Vq3e3', checksum: '349ad5b72aaf2749ca95d847e60c5314', sharedLibFolder: 'lib', includeLibs: ['Release/libPolyVoxCore.so', 'libPolyVoxUtil.so'], ], tbb: [ - file: 'tbb-2018_U1_armv8_libcpp.tgz', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/tbb-2018_U1_armv8_libcpp.tgz', versionId: 'YZliDD8.Menh1IVXKEuLPeO3xAjJ1UdF', checksum: '20768f298f53b195e71b414b0ae240c4', sharedLibFolder: 'lib/release', includeLibs: ['libtbb.so', 'libtbbmalloc.so'], ], hifiAC: [ - file: 'libplugins_libhifiCodec.zip', + file: 'https://hifi-public.s3.amazonaws.com/austin/android/libplugins_libhifiCodec.zip', versionId: 'mzKhsRCgVmloqq5bvE.0IwYK1NjGQc_G', checksum: '9412a8e12c88a4096c1fc843bb9fe52d', sharedLibFolder: '', @@ -150,15 +150,15 @@ def packages = [ def scribeLocalFile='scribe' + EXEC_SUFFIX -def scribeFile='scribe_linux_x86_64' +def scribeFile='https://hifi-public.s3.amazonaws.com/austin/android/scribe_linux_x86_64' def scribeChecksum='ca4b904f52f4f993c29175ba96798fa6' def scribeVersion='wgpf4dB2Ltzg4Lb2jJ4nPFsHoDkmK_OO' if (Os.isFamily(Os.FAMILY_MAC)) { - scribeFile = 'scribe_osx_x86_64' + scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_osx_x86_64' scribeChecksum='72db9d32d4e1e50add755570ac5eb749' scribeVersion='o_NbPrktzEYtBkQf3Tn7zc1nZWzM52w6' } else if (Os.isFamily(Os.FAMILY_WINDOWS)) { - scribeFile = 'scribe_win32_x86_64.exe' + scribeFile = 'https://hifi-public.s3.amazonaws.com/austin/android/scribe_win32_x86_64.exe' scribeChecksum='678e43d290c90fda670c6fefe038a06d' scribeVersion='GCCJxlmd2irvNOFWfZR0U1UCLHndHQrC' } @@ -608,4 +608,4 @@ task testElf (dependsOn: 'externalNativeBuildDebug') { } } } -*/ \ No newline at end of file +*/ diff --git a/cmake/externals/bullet/CMakeLists.txt b/cmake/externals/bullet/CMakeLists.txt index 317e3302d9..91860a7470 100644 --- a/cmake/externals/bullet/CMakeLists.txt +++ b/cmake/externals/bullet/CMakeLists.txt @@ -17,8 +17,8 @@ include(ExternalProject) if (WIN32) ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz - URL_MD5 03051bf112dcc78ddd296f9cab38fd68 + URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz + URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 -DUSE_DX11=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 @@ -28,8 +28,8 @@ if (WIN32) else () ExternalProject_Add( ${EXTERNAL_NAME} - URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.83-ccd-and-cmake-fixes.tgz - URL_MD5 03051bf112dcc78ddd296f9cab38fd68 + URL http://hifi-public.s3.amazonaws.com/dependencies/bullet-2.88.tgz + URL_MD5 0a6876607ebe83e227427215f15946fd CMAKE_ARGS ${PLATFORM_CMAKE_ARGS} -DCMAKE_BUILD_TYPE=RelWithDebInfo -DCMAKE_INSTALL_PREFIX:PATH= -DBUILD_EXTRAS=0 -DINSTALL_LIBS=1 -DBUILD_BULLET3=0 -DBUILD_OPENGL3_DEMOS=0 -DBUILD_BULLET2_DEMOS=0 -DBUILD_UNIT_TESTS=0 -DUSE_GLUT=0 LOG_DOWNLOAD 1 LOG_CONFIGURE 1 diff --git a/cmake/externals/glm/CMakeLists.txt b/cmake/externals/glm/CMakeLists.txt index bc8089074f..0a83004438 100644 --- a/cmake/externals/glm/CMakeLists.txt +++ b/cmake/externals/glm/CMakeLists.txt @@ -3,8 +3,8 @@ set(EXTERNAL_NAME glm) include(ExternalProject) ExternalProject_Add( ${EXTERNAL_NAME} - URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.zip - URL_MD5 579ac77a3110befa3244d68c0ceb7281 + URL https://hifi-public.s3.amazonaws.com/dependencies/glm-0.9.8.5-patched.zip + URL_MD5 7d39ecc1cea275427534c3cfd6dd63f0 BINARY_DIR ${EXTERNAL_PROJECT_PREFIX}/build CMAKE_ARGS -DCMAKE_INSTALL_PREFIX:PATH= ${EXTERNAL_ARGS} LOG_DOWNLOAD 1 @@ -18,4 +18,4 @@ set_target_properties(${EXTERNAL_NAME} PROPERTIES FOLDER "hidden/externals") ExternalProject_Get_Property(${EXTERNAL_NAME} INSTALL_DIR) string(TOUPPER ${EXTERNAL_NAME} EXTERNAL_NAME_UPPER) -set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glm include directories") \ No newline at end of file +set(${EXTERNAL_NAME_UPPER}_INCLUDE_DIRS ${INSTALL_DIR}/include CACHE PATH "List of glm include directories") diff --git a/interface/src/Application.h b/interface/src/Application.h index 3f8e119511..bd3990a25e 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -653,7 +653,7 @@ private: quint64 _lastFaceTrackerUpdate; render::ScenePointer _main3DScene{ new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; - render::EnginePointer _renderEngine{ new render::Engine() }; + render::EnginePointer _renderEngine{ new render::RenderEngine() }; gpu::ContextPointer _gpuContext; // initialized during window creation GameWorkload _gameWorkload; diff --git a/interface/src/avatar/AvatarMotionState.cpp b/interface/src/avatar/AvatarMotionState.cpp index beb7e34439..6fc1bd8196 100644 --- a/interface/src/avatar/AvatarMotionState.cpp +++ b/interface/src/avatar/AvatarMotionState.cpp @@ -160,7 +160,7 @@ QUuid AvatarMotionState::getSimulatorID() const { } // virtual -void AvatarMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { +void AvatarMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const { group = BULLET_COLLISION_GROUP_OTHER_AVATAR; mask = Physics::getDefaultCollisionMask(group); } diff --git a/interface/src/avatar/AvatarMotionState.h b/interface/src/avatar/AvatarMotionState.h index 73fb853312..2738aba8ee 100644 --- a/interface/src/avatar/AvatarMotionState.h +++ b/interface/src/avatar/AvatarMotionState.h @@ -65,7 +65,7 @@ public: void addDirtyFlags(uint32_t flags) { _dirtyFlags |= flags; } - virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; + virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override; virtual float getMass() const override; diff --git a/interface/src/avatar/MyAvatar.h b/interface/src/avatar/MyAvatar.h index fa6a675d99..a1eb29b38b 100644 --- a/interface/src/avatar/MyAvatar.h +++ b/interface/src/avatar/MyAvatar.h @@ -1402,7 +1402,7 @@ private: SharedSoundPointer _collisionSound; MyCharacterController _characterController; - int16_t _previousCollisionGroup { BULLET_COLLISION_GROUP_MY_AVATAR }; + int32_t _previousCollisionGroup { BULLET_COLLISION_GROUP_MY_AVATAR }; AvatarWeakPointer _lookAtTargetAvatar; glm::vec3 _targetAvatarPosition; diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index c177cfb7cf..87bf093224 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -53,7 +53,7 @@ GameWorkloadContext::~GameWorkloadContext() { GameWorkload::GameWorkload() : - _engine(std::make_shared(WorkloadEngineBuilder::JobModel::create("Engine"))) + _engine(std::make_shared(WorkloadEngineBuilder::JobModel::create("Workload"), std::shared_ptr())) { } diff --git a/libraries/entities/src/EntityItem.cpp b/libraries/entities/src/EntityItem.cpp index 8ad8527821..bb085796d3 100644 --- a/libraries/entities/src/EntityItem.cpp +++ b/libraries/entities/src/EntityItem.cpp @@ -842,7 +842,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY(PROP_COLLISIONLESS, bool, setCollisionless); - READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint8_t, setCollisionMask); + READ_ENTITY_PROPERTY(PROP_COLLISION_MASK, uint16_t, setCollisionMask); READ_ENTITY_PROPERTY(PROP_DYNAMIC, bool, setDynamic); READ_ENTITY_PROPERTY(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY(PROP_USER_DATA, QString, setUserData); @@ -1895,7 +1895,7 @@ void EntityItem::setCollisionless(bool value) { }); } -void EntityItem::setCollisionMask(uint8_t value) { +void EntityItem::setCollisionMask(uint16_t value) { withWriteLock([&] { if ((_collisionMask & ENTITY_COLLISION_MASK_DEFAULT) != (value & ENTITY_COLLISION_MASK_DEFAULT)) { _collisionMask = (value & ENTITY_COLLISION_MASK_DEFAULT); @@ -1960,7 +1960,7 @@ void EntityItem::setCreated(quint64 value) { }); } -void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const { +void EntityItem::computeCollisionGroupAndFinalMask(int32_t& group, int32_t& mask) const { if (_collisionless) { group = BULLET_COLLISION_GROUP_COLLISIONLESS; mask = 0; @@ -1973,7 +1973,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask group = BULLET_COLLISION_GROUP_STATIC; } - uint8_t userMask = getCollisionMask(); + uint16_t userMask = getCollisionMask(); if ((bool)(userMask & USER_COLLISION_GROUP_MY_AVATAR) != (bool)(userMask & USER_COLLISION_GROUP_OTHER_AVATAR)) { @@ -1987,7 +1987,7 @@ void EntityItem::computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask if ((bool)(_flags & Simulation::SPECIAL_FLAGS_NO_BOOTSTRAPPING)) { userMask &= ~USER_COLLISION_GROUP_MY_AVATAR; } - mask = Physics::getDefaultCollisionMask(group) & (int16_t)(userMask); + mask = Physics::getDefaultCollisionMask(group) & (int32_t)(userMask); } } @@ -2843,8 +2843,8 @@ bool EntityItem::getCollisionless() const { return result; } -uint8_t EntityItem::getCollisionMask() const { - uint8_t result; +uint16_t EntityItem::getCollisionMask() const { + uint16_t result; withReadLock([&] { result = _collisionMask; }); diff --git a/libraries/entities/src/EntityItem.h b/libraries/entities/src/EntityItem.h index 8225d4692c..43a69b1761 100644 --- a/libraries/entities/src/EntityItem.h +++ b/libraries/entities/src/EntityItem.h @@ -288,10 +288,10 @@ public: bool getCollisionless() const; void setCollisionless(bool value); - uint8_t getCollisionMask() const; - void setCollisionMask(uint8_t value); + uint16_t getCollisionMask() const; + void setCollisionMask(uint16_t value); - void computeCollisionGroupAndFinalMask(int16_t& group, int16_t& mask) const; + void computeCollisionGroupAndFinalMask(int32_t& group, int32_t& mask) const; bool getDynamic() const; void setDynamic(bool value); @@ -592,7 +592,7 @@ protected: bool _visible { ENTITY_ITEM_DEFAULT_VISIBLE }; bool _canCastShadow{ ENTITY_ITEM_DEFAULT_CAN_CAST_SHADOW }; bool _collisionless { ENTITY_ITEM_DEFAULT_COLLISIONLESS }; - uint8_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; + uint16_t _collisionMask { ENTITY_COLLISION_MASK_DEFAULT }; bool _dynamic { ENTITY_ITEM_DEFAULT_DYNAMIC }; bool _locked { ENTITY_ITEM_DEFAULT_LOCKED }; QString _userData { ENTITY_ITEM_DEFAULT_USER_DATA }; diff --git a/libraries/entities/src/EntityItemProperties.cpp b/libraries/entities/src/EntityItemProperties.cpp index 30e2b13daf..949b39bb7d 100644 --- a/libraries/entities/src/EntityItemProperties.cpp +++ b/libraries/entities/src/EntityItemProperties.cpp @@ -130,7 +130,7 @@ void buildStringToMaterialMappingModeLookup() { addMaterialMappingMode(PROJECTED); } -QString getCollisionGroupAsString(uint8_t group) { +QString getCollisionGroupAsString(uint16_t group) { switch (group) { case USER_COLLISION_GROUP_DYNAMIC: return "dynamic"; @@ -146,7 +146,7 @@ QString getCollisionGroupAsString(uint8_t group) { return ""; } -uint8_t getCollisionGroupAsBitMask(const QStringRef& name) { +uint16_t getCollisionGroupAsBitMask(const QStringRef& name) { if (0 == name.compare(QString("dynamic"))) { return USER_COLLISION_GROUP_DYNAMIC; } else if (0 == name.compare(QString("static"))) { @@ -164,7 +164,7 @@ uint8_t getCollisionGroupAsBitMask(const QStringRef& name) { QString EntityItemProperties::getCollisionMaskAsString() const { QString maskString(""); for (int i = 0; i < NUM_USER_COLLISION_GROUPS; ++i) { - uint8_t group = 0x01 << i; + uint16_t group = 0x0001 << i; if (group & _collisionMask) { maskString.append(getCollisionGroupAsString(group)); maskString.append(','); @@ -175,7 +175,7 @@ QString EntityItemProperties::getCollisionMaskAsString() const { void EntityItemProperties::setCollisionMaskFromString(const QString& maskString) { QVector groups = maskString.splitRef(','); - uint8_t mask = 0x00; + uint16_t mask = 0x0000; for (auto groupName : groups) { mask |= getCollisionGroupAsBitMask(groupName); } @@ -1520,7 +1520,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool COPY_PROPERTY_FROM_QSCRIPTVALUE(localRenderAlpha, float, setLocalRenderAlpha); COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionless, bool, setCollisionless); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(ignoreForCollisions, bool, setCollisionless, getCollisionless); // legacy support - COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint8_t, setCollisionMask); + COPY_PROPERTY_FROM_QSCRIPTVALUE(collisionMask, uint16_t, setCollisionMask); COPY_PROPERTY_FROM_QSCRIPTVALUE_ENUM(collidesWith, CollisionMask); COPY_PROPERTY_FROM_QSCRIPTVALUE_GETTER(collisionsWillMove, bool, setDynamic, getDynamic); // legacy support COPY_PROPERTY_FROM_QSCRIPTVALUE(dynamic, bool, setDynamic); @@ -2576,7 +2576,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_VISIBLE, bool, setVisible); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_CAN_CAST_SHADOW, bool, setCanCastShadow); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISIONLESS, bool, setCollisionless); - READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint8_t, setCollisionMask); + READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLLISION_MASK, uint16_t, setCollisionMask); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DYNAMIC, bool, setDynamic); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LOCKED, bool, setLocked); READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_USER_DATA, QString, setUserData); diff --git a/libraries/entities/src/EntityItemProperties.h b/libraries/entities/src/EntityItemProperties.h index be8e72844d..b91771892f 100644 --- a/libraries/entities/src/EntityItemProperties.h +++ b/libraries/entities/src/EntityItemProperties.h @@ -148,7 +148,7 @@ public: DEFINE_PROPERTY_REF(PROP_ANGULAR_VELOCITY, AngularVelocity, angularVelocity, glm::vec3, ENTITY_ITEM_DEFAULT_ANGULAR_VELOCITY); DEFINE_PROPERTY(PROP_ANGULAR_DAMPING, AngularDamping, angularDamping, float, ENTITY_ITEM_DEFAULT_ANGULAR_DAMPING); DEFINE_PROPERTY(PROP_COLLISIONLESS, Collisionless, collisionless, bool, ENTITY_ITEM_DEFAULT_COLLISIONLESS); - DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint8_t, ENTITY_COLLISION_MASK_DEFAULT); + DEFINE_PROPERTY(PROP_COLLISION_MASK, CollisionMask, collisionMask, uint16_t, ENTITY_COLLISION_MASK_DEFAULT); DEFINE_PROPERTY(PROP_DYNAMIC, Dynamic, dynamic, bool, ENTITY_ITEM_DEFAULT_DYNAMIC); DEFINE_PROPERTY(PROP_IS_SPOTLIGHT, IsSpotlight, isSpotlight, bool, LightEntityItem::DEFAULT_IS_SPOTLIGHT); DEFINE_PROPERTY(PROP_INTENSITY, Intensity, intensity, float, LightEntityItem::DEFAULT_INTENSITY); diff --git a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp index 503e1df922..a255cc5878 100644 --- a/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl41/GL41BackendTexture.cpp @@ -31,6 +31,10 @@ bool GL41Backend::supportedTextureFormat(const gpu::Element& format) { case gpu::Semantic::COMPRESSED_EAC_RED_SIGNED: case gpu::Semantic::COMPRESSED_EAC_XY: case gpu::Semantic::COMPRESSED_EAC_XY_SIGNED: + // The ARB_texture_compression_bptc extension is not supported on 4.1 + // See https://www.g-truc.net/doc/OpenGL%204%20Hardware%20Matrix.pdf + case gpu::Semantic::COMPRESSED_BC6_RGB: + case gpu::Semantic::COMPRESSED_BC7_SRGBA: return false; default: return true; diff --git a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp index 558f221705..fda7ac22dd 100644 --- a/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp +++ b/libraries/gpu-gl/src/gpu/gl45/GL45BackendTexture.cpp @@ -33,6 +33,8 @@ using namespace gpu::gl45; bool GL45Backend::supportedTextureFormat(const gpu::Element& format) { switch (format.getSemantic()) { + // ETC textures are actually required by the OpenGL spec as of 4.3, but aren't always supported by hardware + // They'll be recompressed by OpenGL, which will be slow or have poor quality, so disable them for now case gpu::Semantic::COMPRESSED_ETC2_RGB: case gpu::Semantic::COMPRESSED_ETC2_SRGB: case gpu::Semantic::COMPRESSED_ETC2_RGB_PUNCHTHROUGH_ALPHA: diff --git a/libraries/networking/src/udt/PacketHeaders.cpp b/libraries/networking/src/udt/PacketHeaders.cpp index c07c5905f6..b69733c18d 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::CloneableData); + return static_cast(EntityVersion::CollisionMask16Bytes); 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 29d4efed42..5203a9d178 100644 --- a/libraries/networking/src/udt/PacketHeaders.h +++ b/libraries/networking/src/udt/PacketHeaders.h @@ -235,7 +235,8 @@ enum class EntityVersion : PacketVersion { MaterialEntities, ShadowControl, MaterialData, - CloneableData + CloneableData, + CollisionMask16Bytes }; enum class EntityScriptCallMethodVersion : PacketVersion { diff --git a/libraries/physics/src/CharacterController.cpp b/libraries/physics/src/CharacterController.cpp index 9b6e9fe7a0..64eda975cf 100755 --- a/libraries/physics/src/CharacterController.cpp +++ b/libraries/physics/src/CharacterController.cpp @@ -109,7 +109,7 @@ void CharacterController::setDynamicsWorld(btDynamicsWorld* world) { } _dynamicsWorld = nullptr; } - int16_t collisionGroup = computeCollisionGroup(); + int32_t collisionGroup = computeCollisionGroup(); if (_rigidBody) { updateMassProperties(); } @@ -325,7 +325,7 @@ void CharacterController::playerStep(btCollisionWorld* collisionWorld, btScalar _ghost.setWorldTransform(_rigidBody->getWorldTransform()); } -void CharacterController::jump() { +void CharacterController::jump(const btVector3& dir) { _pendingFlags |= PENDING_FLAG_JUMP; } @@ -352,7 +352,7 @@ static const char* stateToStr(CharacterController::State state) { #endif // #ifdef DEBUG_STATE_CHANGE void CharacterController::updateCurrentGravity() { - int16_t collisionGroup = computeCollisionGroup(); + int32_t collisionGroup = computeCollisionGroup(); if (_state == State::Hover || collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS) { _currentGravity = 0.0f; } else { @@ -433,7 +433,7 @@ void CharacterController::setCollisionless(bool collisionless) { } } -int16_t CharacterController::computeCollisionGroup() const { +int32_t CharacterController::computeCollisionGroup() const { if (_collisionless) { return _collisionlessAllowed ? BULLET_COLLISION_GROUP_COLLISIONLESS : BULLET_COLLISION_GROUP_MY_AVATAR; } else { @@ -446,7 +446,7 @@ void CharacterController::handleChangedCollisionGroup() { // ATM the easiest way to update collision groups is to remove/re-add the RigidBody if (_dynamicsWorld) { _dynamicsWorld->removeRigidBody(_rigidBody); - int16_t collisionGroup = computeCollisionGroup(); + int32_t collisionGroup = computeCollisionGroup(); _dynamicsWorld->addRigidBody(_rigidBody, collisionGroup, BULLET_COLLISION_MASK_MY_AVATAR); } _pendingFlags &= ~PENDING_FLAG_UPDATE_COLLISION_GROUP; @@ -538,7 +538,7 @@ void CharacterController::applyMotor(int index, btScalar dt, btVector3& worldVel btScalar angle = motor.rotation.getAngle(); btVector3 velocity = worldVelocity.rotate(axis, -angle); - int16_t collisionGroup = computeCollisionGroup(); + int32_t collisionGroup = computeCollisionGroup(); if (collisionGroup == BULLET_COLLISION_GROUP_COLLISIONLESS || _state == State::Hover || motor.hTimescale == motor.vTimescale) { // modify velocity @@ -679,7 +679,7 @@ void CharacterController::updateState() { btVector3 rayStart = _position; btScalar rayLength = _radius; - int16_t collisionGroup = computeCollisionGroup(); + int32_t collisionGroup = computeCollisionGroup(); if (collisionGroup == BULLET_COLLISION_GROUP_MY_AVATAR) { rayLength += _scaleFactor * DEFAULT_AVATAR_FALL_HEIGHT; } else { diff --git a/libraries/physics/src/CharacterController.h b/libraries/physics/src/CharacterController.h index 96e479dcad..50db2bea12 100644 --- a/libraries/physics/src/CharacterController.h +++ b/libraries/physics/src/CharacterController.h @@ -70,7 +70,7 @@ public: virtual void preStep(btCollisionWorld *collisionWorld) override; virtual void playerStep(btCollisionWorld *collisionWorld, btScalar dt) override; virtual bool canJump() const override { assert(false); return false; } // never call this - virtual void jump() override; + virtual void jump(const btVector3& dir = btVector3(0.0f, 0.0f, 0.0f)) override; virtual bool onGround() const override; void clearMotors(); @@ -120,7 +120,7 @@ public: bool isStuck() const { return _isStuck; } void setCollisionless(bool collisionless); - int16_t computeCollisionGroup() const; + int32_t computeCollisionGroup() const; void handleChangedCollisionGroup(); bool getRigidBodyLocation(glm::vec3& avatarRigidBodyPosition, glm::quat& avatarRigidBodyRotation); diff --git a/libraries/physics/src/CharacterGhostObject.cpp b/libraries/physics/src/CharacterGhostObject.cpp index 331485dd01..a771a52384 100755 --- a/libraries/physics/src/CharacterGhostObject.cpp +++ b/libraries/physics/src/CharacterGhostObject.cpp @@ -29,13 +29,13 @@ CharacterGhostObject::~CharacterGhostObject() { } } -void CharacterGhostObject::setCollisionGroupAndMask(int16_t group, int16_t mask) { +void CharacterGhostObject::setCollisionGroupAndMask(int32_t group, int32_t mask) { _collisionFilterGroup = group; _collisionFilterMask = mask; // TODO: if this probe is in the world reset ghostObject overlap cache } -void CharacterGhostObject::getCollisionGroupAndMask(int16_t& group, int16_t& mask) const { +void CharacterGhostObject::getCollisionGroupAndMask(int32_t& group, int32_t& mask) const { group = _collisionFilterGroup; mask = _collisionFilterMask; } diff --git a/libraries/physics/src/CharacterGhostObject.h b/libraries/physics/src/CharacterGhostObject.h index 1e4625c6f6..44ab5c938a 100755 --- a/libraries/physics/src/CharacterGhostObject.h +++ b/libraries/physics/src/CharacterGhostObject.h @@ -28,8 +28,8 @@ public: CharacterGhostObject() { } ~CharacterGhostObject(); - void setCollisionGroupAndMask(int16_t group, int16_t mask); - void getCollisionGroupAndMask(int16_t& group, int16_t& mask) const; + void setCollisionGroupAndMask(int32_t group, int32_t mask); + void getCollisionGroupAndMask(int32_t& group, int32_t& mask) const; void setRadiusAndHalfHeight(btScalar radius, btScalar halfHeight); void setUpDirection(const btVector3& up); @@ -54,8 +54,8 @@ protected: btScalar _radius { 0.0f }; btConvexHullShape* _characterShape { nullptr }; // input, shape of character CharacterGhostShape* _ghostShape { nullptr }; // internal, shape whose Aabb is used for overlap cache - int16_t _collisionFilterGroup { 0 }; - int16_t _collisionFilterMask { 0 }; + int32_t _collisionFilterGroup { 0 }; + int32_t _collisionFilterMask { 0 }; bool _inWorld { false }; // internal, was added to world }; diff --git a/libraries/physics/src/EntityMotionState.cpp b/libraries/physics/src/EntityMotionState.cpp index 4690b11db3..bc293b785b 100644 --- a/libraries/physics/src/EntityMotionState.cpp +++ b/libraries/physics/src/EntityMotionState.cpp @@ -779,7 +779,7 @@ QString EntityMotionState::getName() const { } // virtual -void EntityMotionState::computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const { +void EntityMotionState::computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const { _entity->computeCollisionGroupAndFinalMask(group, mask); } diff --git a/libraries/physics/src/EntityMotionState.h b/libraries/physics/src/EntityMotionState.h index 9e91c316c6..96c307a85a 100644 --- a/libraries/physics/src/EntityMotionState.h +++ b/libraries/physics/src/EntityMotionState.h @@ -85,7 +85,7 @@ public: virtual QString getName() const override; - virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const override; + virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const override; bool shouldSendBid(); uint8_t computeFinalBidPriority() const; diff --git a/libraries/physics/src/ObjectMotionState.h b/libraries/physics/src/ObjectMotionState.h index e1cf5a4285..24dd655342 100644 --- a/libraries/physics/src/ObjectMotionState.h +++ b/libraries/physics/src/ObjectMotionState.h @@ -154,7 +154,7 @@ public: virtual QString getName() const { return ""; } - virtual void computeCollisionGroupAndMask(int16_t& group, int16_t& mask) const = 0; + virtual void computeCollisionGroupAndMask(int32_t& group, int32_t& mask) const = 0; bool isActive() const { return _body ? _body->isActive() : false; } diff --git a/libraries/physics/src/PhysicsEngine.cpp b/libraries/physics/src/PhysicsEngine.cpp index 47971b238a..fc54970585 100644 --- a/libraries/physics/src/PhysicsEngine.cpp +++ b/libraries/physics/src/PhysicsEngine.cpp @@ -149,7 +149,7 @@ void PhysicsEngine::addObjectToDynamicsWorld(ObjectMotionState* motionState) { body->setFlags(BT_DISABLE_WORLD_GRAVITY); motionState->updateBodyMaterialProperties(); - int16_t group, mask; + int32_t group, mask; motionState->computeCollisionGroupAndMask(group, mask); _dynamicsWorld->addRigidBody(body, group, mask); diff --git a/libraries/render-utils/src/AmbientOcclusionEffect.h b/libraries/render-utils/src/AmbientOcclusionEffect.h index 3643e608ed..b3a93ab1de 100644 --- a/libraries/render-utils/src/AmbientOcclusionEffect.h +++ b/libraries/render-utils/src/AmbientOcclusionEffect.h @@ -181,7 +181,7 @@ class DebugAmbientOcclusionConfig : public render::Job::Config { Q_PROPERTY(bool showCursorPixel MEMBER showCursorPixel NOTIFY dirty) Q_PROPERTY(glm::vec2 debugCursorTexcoord MEMBER debugCursorTexcoord NOTIFY dirty) public: - DebugAmbientOcclusionConfig() : render::Job::Config(true) {} + DebugAmbientOcclusionConfig() : render::Job::Config(false) {} bool showCursorPixel{ false }; glm::vec2 debugCursorTexcoord{ 0.5f, 0.5f }; diff --git a/libraries/render-utils/src/GeometryCache.cpp b/libraries/render-utils/src/GeometryCache.cpp index 0d8561ad21..f8f49921a3 100644 --- a/libraries/render-utils/src/GeometryCache.cpp +++ b/libraries/render-utils/src/GeometryCache.cpp @@ -122,6 +122,9 @@ static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW } static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT; static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; +static gpu::Stream::FormatPointer WIRE_STREAM_FORMAT; +static gpu::Stream::FormatPointer INSTANCED_WIRE_STREAM_FORMAT; +static gpu::Stream::FormatPointer INSTANCED_WIRE_FADE_STREAM_FORMAT; static const uint SHAPE_VERTEX_STRIDE = sizeof(GeometryCache::ShapeVertex); // position, normal, texcoords, tangent static const uint SHAPE_NORMALS_OFFSET = offsetof(GeometryCache::ShapeVertex, normal); @@ -690,6 +693,38 @@ gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() { return INSTANCED_SOLID_FADE_STREAM_FORMAT; } +gpu::Stream::FormatPointer& getWireStreamFormat() { + if (!WIRE_STREAM_FORMAT) { + WIRE_STREAM_FORMAT = std::make_shared(); // 1 for everyone + WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); + WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); + } + return WIRE_STREAM_FORMAT; +} + +gpu::Stream::FormatPointer& getInstancedWireStreamFormat() { + if (!INSTANCED_WIRE_STREAM_FORMAT) { + INSTANCED_WIRE_STREAM_FORMAT = std::make_shared(); // 1 for everyone + INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); + INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); + INSTANCED_WIRE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + } + return INSTANCED_WIRE_STREAM_FORMAT; +} + +gpu::Stream::FormatPointer& getInstancedWireFadeStreamFormat() { + if (!INSTANCED_WIRE_FADE_STREAM_FORMAT) { + INSTANCED_WIRE_FADE_STREAM_FORMAT = std::make_shared(); // 1 for everyone + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT); + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT); + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + INSTANCED_WIRE_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE); + } + return INSTANCED_WIRE_FADE_STREAM_FORMAT; +} + QHash GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader; @@ -827,7 +862,7 @@ void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) { } void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) { - batch.setInputFormat(getSolidStreamFormat()); + batch.setInputFormat(getWireStreamFormat()); _shapes[shape].drawWire(batch); } @@ -839,7 +874,7 @@ void GeometryCache::renderShape(gpu::Batch& batch, Shape shape, const glm::vec4& } void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape, const glm::vec4& color) { - batch.setInputFormat(getSolidStreamFormat()); + batch.setInputFormat(getWireStreamFormat()); // Color must be set after input format batch._glColor4f(color.r, color.g, color.b, color.a); _shapes[shape].drawWire(batch); @@ -857,7 +892,7 @@ void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t } void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer) { - batch.setInputFormat(getInstancedSolidStreamFormat()); + batch.setInputFormat(getInstancedWireStreamFormat()); setupBatchInstance(batch, colorBuffer); _shapes[shape].drawWireInstances(batch, count); } @@ -883,7 +918,7 @@ void GeometryCache::renderFadeShapeInstances(gpu::Batch& batch, Shape shape, siz void GeometryCache::renderWireFadeShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer, gpu::BufferPointer& fadeBuffer1, gpu::BufferPointer& fadeBuffer2, gpu::BufferPointer& fadeBuffer3) { - batch.setInputFormat(getInstancedSolidFadeStreamFormat()); + batch.setInputFormat(getInstancedWireFadeStreamFormat()); setupBatchFadeInstance(batch, colorBuffer, fadeBuffer1, fadeBuffer2, fadeBuffer3); _shapes[shape].drawWireInstances(batch, count); } diff --git a/libraries/render-utils/src/LightClusters.h b/libraries/render-utils/src/LightClusters.h index f495dabebb..fa054c304a 100644 --- a/libraries/render-utils/src/LightClusters.h +++ b/libraries/render-utils/src/LightClusters.h @@ -195,7 +195,7 @@ class DebugLightClustersConfig : public render::Job::Config { Q_PROPERTY(bool doDrawClusterFromDepth MEMBER doDrawClusterFromDepth NOTIFY dirty) Q_PROPERTY(bool doDrawContent MEMBER doDrawContent NOTIFY dirty) public: - DebugLightClustersConfig() : render::Job::Config(true){} + DebugLightClustersConfig() : render::Job::Config(false){} bool doDrawGrid{ false }; diff --git a/libraries/render/src/render/Engine.cpp b/libraries/render/src/render/Engine.cpp index b0842d63cd..da8e60d40a 100644 --- a/libraries/render/src/render/Engine.cpp +++ b/libraries/render/src/render/Engine.cpp @@ -36,12 +36,11 @@ public: } }; -Engine::Engine() : Task(EngineTask::JobModel::create("Engine")), - _renderContext(std::make_shared()) +RenderEngine::RenderEngine() : Engine(EngineTask::JobModel::create("Engine"), std::make_shared()) { } -void Engine::load() { +void RenderEngine::load() { auto config = getConfiguration(); const QString configFile= "config/render.json"; diff --git a/libraries/render/src/render/Engine.h b/libraries/render/src/render/Engine.h index 0271c71529..130ed6533f 100644 --- a/libraries/render/src/render/Engine.h +++ b/libraries/render/src/render/Engine.h @@ -25,7 +25,7 @@ namespace render { class RenderContext : public task::JobContext { public: - RenderContext() : task::JobContext(trace_render()) {} + RenderContext() : task::JobContext() {} virtual ~RenderContext() {} RenderArgs* args; @@ -33,7 +33,9 @@ namespace render { }; using RenderContextPointer = std::shared_ptr; - Task_DeclareTypeAliases(RenderContext) + Task_DeclareCategoryTimeProfilerClass(RenderTimeProfiler, trace_render); + + Task_DeclareTypeAliases(RenderContext, RenderTimeProfiler) // Versions of the COnfig integrating a gpu & batch timer class GPUJobConfig : public JobConfig { @@ -57,10 +59,10 @@ namespace render { class GPUTaskConfig : public TaskConfig { Q_OBJECT - Q_PROPERTY(double gpuRunTime READ getGPURunTime) - Q_PROPERTY(double batchRunTime READ getBatchRunTime) + Q_PROPERTY(double gpuRunTime READ getGPURunTime) + Q_PROPERTY(double batchRunTime READ getBatchRunTime) - double _msGPURunTime { 0.0 }; + double _msGPURunTime { 0.0 }; double _msBatchRunTime { 0.0 }; public: @@ -80,32 +82,25 @@ namespace render { // The render engine holds all render tasks, and is itself a render task. // State flows through tasks to jobs via the render and scene contexts - // the engine should not be known from its jobs. - class Engine : public Task { + class RenderEngine : public Engine { public: - Engine(); - ~Engine() = default; + RenderEngine(); + ~RenderEngine() = default; // Load any persisted settings, and set up the presets // This should be run after adding all jobs, and before building ui void load(); // Register the scene - void registerScene(const ScenePointer& scene) { _renderContext->_scene = scene; } + void registerScene(const ScenePointer& scene) { _context->_scene = scene; } // acces the RenderContext - RenderContextPointer getRenderContext() const { return _renderContext; } - - // Render a frame - // Must have a scene registered and a context set - void run() { assert(_renderContext); Task::run(_renderContext); } + RenderContextPointer getRenderContext() const { return _context; } protected: - RenderContextPointer _renderContext; - - void run(const RenderContextPointer& context) override { assert(_renderContext); Task::run(_renderContext); } }; - using EnginePointer = std::shared_ptr; + using EnginePointer = std::shared_ptr; } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 2d8bc7f4dd..68acfe8d0f 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -21,7 +21,7 @@ namespace render { -class Engine; +class RenderEngine; class Scene; // Transaction is the mechanism to make any change to the scene. @@ -236,7 +236,7 @@ protected: StageMap _stages; - friend class Engine; + friend class RenderEngine; }; typedef std::shared_ptr ScenePointer; diff --git a/libraries/shared/src/PhysicsCollisionGroups.h b/libraries/shared/src/PhysicsCollisionGroups.h index edec61dc67..9d99ec3532 100644 --- a/libraries/shared/src/PhysicsCollisionGroups.h +++ b/libraries/shared/src/PhysicsCollisionGroups.h @@ -34,13 +34,13 @@ enum CollisionFilterGroups { * */ -const int16_t BULLET_COLLISION_GROUP_STATIC = 1 << 0; -const int16_t BULLET_COLLISION_GROUP_DYNAMIC = 1 << 1; -const int16_t BULLET_COLLISION_GROUP_KINEMATIC = 1 << 2; -const int16_t BULLET_COLLISION_GROUP_MY_AVATAR = 1 << 3; -const int16_t BULLET_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; +const int32_t BULLET_COLLISION_GROUP_STATIC = 1 << 0; +const int32_t BULLET_COLLISION_GROUP_DYNAMIC = 1 << 1; +const int32_t BULLET_COLLISION_GROUP_KINEMATIC = 1 << 2; +const int32_t BULLET_COLLISION_GROUP_MY_AVATAR = 1 << 3; +const int32_t BULLET_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; // ... -const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14; +const int32_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 31; /* Note: In order for objectA to collide with objectB at the filter stage @@ -48,21 +48,21 @@ const int16_t BULLET_COLLISION_GROUP_COLLISIONLESS = 1 << 14; */ // the default collision mask is: collides with everything except collisionless -const int16_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS; +const int32_t BULLET_COLLISION_MASK_DEFAULT = ~ BULLET_COLLISION_GROUP_COLLISIONLESS; // STATIC does not collide with itself (as optimization of physics simulation) -const int16_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC); +const int32_t BULLET_COLLISION_MASK_STATIC = ~ (BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_KINEMATIC | BULLET_COLLISION_GROUP_STATIC); -const int16_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT; -const int16_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC; +const int32_t BULLET_COLLISION_MASK_DYNAMIC = BULLET_COLLISION_MASK_DEFAULT; +const int32_t BULLET_COLLISION_MASK_KINEMATIC = BULLET_COLLISION_MASK_STATIC; // MY_AVATAR does not collide with itself -const int16_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR); +const int32_t BULLET_COLLISION_MASK_MY_AVATAR = ~(BULLET_COLLISION_GROUP_COLLISIONLESS | BULLET_COLLISION_GROUP_MY_AVATAR); -const int16_t BULLET_COLLISION_MASK_OTHER_AVATAR = BULLET_COLLISION_MASK_DEFAULT; +const int32_t BULLET_COLLISION_MASK_OTHER_AVATAR = BULLET_COLLISION_MASK_DEFAULT; // COLLISIONLESS gets an empty mask. -const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; +const int32_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; /**jsdoc *

An entity may collide with the following types of items:

@@ -72,35 +72,35 @@ const int16_t BULLET_COLLISION_MASK_COLLISIONLESS = 0; * * * 1Static entities — non-dynamic entities with no velocity. - * 2Dynamic entities — entities that have their dynamic property set to + * 2Dynamic entities — entities that have their dynamic property set to * true. * 4Kinematic entities — non-dynamic entities with velocity. * 8My avatar. * 16Other avatars. * * - *

The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a + *

The values for the collision types that are enabled are added together to give the CollisionMask value. For example, a * value of 31 means that an entity will collide with all item types.

* @typedef {number} Entities.CollisionMask */ // The USER collision groups are exposed to script and can be used to generate per-object collision masks. // They are not necessarily the same as the BULLET_COLLISION_GROUPS, but we start them off with matching numbers. -const uint8_t USER_COLLISION_GROUP_STATIC = 1 << 0; -const uint8_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1; -const uint8_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2; -const uint8_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3; -const uint8_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; +const uint16_t USER_COLLISION_GROUP_STATIC = 1 << 0; +const uint16_t USER_COLLISION_GROUP_DYNAMIC = 1 << 1; +const uint16_t USER_COLLISION_GROUP_KINEMATIC = 1 << 2; +const uint16_t USER_COLLISION_GROUP_MY_AVATAR = 1 << 3; +const uint16_t USER_COLLISION_GROUP_OTHER_AVATAR = 1 << 4; -const uint8_t ENTITY_COLLISION_MASK_DEFAULT = +const uint16_t ENTITY_COLLISION_MASK_DEFAULT = USER_COLLISION_GROUP_STATIC | USER_COLLISION_GROUP_DYNAMIC | USER_COLLISION_GROUP_KINEMATIC | USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; -const uint8_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; +const uint16_t USER_COLLISION_MASK_AVATARS = USER_COLLISION_GROUP_MY_AVATAR | USER_COLLISION_GROUP_OTHER_AVATAR; -const int NUM_USER_COLLISION_GROUPS = 5; +const int32_t NUM_USER_COLLISION_GROUPS = 5; #endif // hifi_PhysicsCollisionGroups_h diff --git a/libraries/shared/src/PhysicsHelpers.cpp b/libraries/shared/src/PhysicsHelpers.cpp index 18accfd799..b43d55020e 100644 --- a/libraries/shared/src/PhysicsHelpers.cpp +++ b/libraries/shared/src/PhysicsHelpers.cpp @@ -61,7 +61,7 @@ glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float time } /* end Bullet code derivation*/ -int16_t Physics::getDefaultCollisionMask(int16_t group) { +int32_t Physics::getDefaultCollisionMask(int32_t group) { switch(group) { case BULLET_COLLISION_GROUP_STATIC: return BULLET_COLLISION_MASK_STATIC; diff --git a/libraries/shared/src/PhysicsHelpers.h b/libraries/shared/src/PhysicsHelpers.h index 67442187a3..332100f03b 100644 --- a/libraries/shared/src/PhysicsHelpers.h +++ b/libraries/shared/src/PhysicsHelpers.h @@ -31,7 +31,7 @@ const float KINEMATIC_ANGULAR_SPEED_THRESHOLD = 0.008f; // ~0.5 deg/sec glm::quat computeBulletRotationStep(const glm::vec3& angularVelocity, float timeStep); namespace Physics { - int16_t getDefaultCollisionMask(int16_t group); + int32_t getDefaultCollisionMask(int32_t group); void setSessionUUID(const QUuid& sessionID); const QUuid& getSessionUUID(); diff --git a/libraries/task/src/task/Config.h b/libraries/task/src/task/Config.h index fc803bea1a..ec504efef0 100644 --- a/libraries/task/src/task/Config.h +++ b/libraries/task/src/task/Config.h @@ -123,9 +123,10 @@ public: // Running Time measurement // The new stats signal is emitted once per run time of a job when stats (cpu runtime) are updated - void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = runtime.count() / 1000000.0; emit newStats(); } + void setCPURunTime(const std::chrono::nanoseconds& runtime) { _msCPURunTime = std::chrono::duration(runtime).count(); emit newStats(); } double getCPURunTime() const { return _msCPURunTime; } + // Describe the node graph data connections of the associated Job/Task Q_INVOKABLE virtual bool isTask() const { return false; } Q_INVOKABLE virtual QObjectList getSubConfigs() const { return QObjectList(); } Q_INVOKABLE virtual int getNumSubs() const { return 0; } @@ -185,6 +186,7 @@ public: TaskConfig() = default; TaskConfig(bool enabled) : JobConfig(enabled) {} + /**jsdoc * @function Render.getConfig * @param {string} name @@ -231,11 +233,10 @@ public: } return returned; } - Q_INVOKABLE int getNumSubs() const override { return getSubConfigs().size(); } Q_INVOKABLE QObject* getSubConfig(int i) const override { auto subs = getSubConfigs(); - return ((i < 0 || i >= subs.size()) ? nullptr : subs[i] ); + return ((i < 0 || i >= subs.size()) ? nullptr : subs[i]); } void connectChildConfig(QConfigPointer childConfig, const std::string& name); diff --git a/libraries/task/src/task/Task.cpp b/libraries/task/src/task/Task.cpp index 621d77d7bf..9123ef8b04 100644 --- a/libraries/task/src/task/Task.cpp +++ b/libraries/task/src/task/Task.cpp @@ -12,9 +12,7 @@ using namespace task; -JobContext::JobContext(const QLoggingCategory& category) : - profileCategory(category) { - assert(&category); +JobContext::JobContext() { } JobContext::~JobContext() { diff --git a/libraries/task/src/task/Task.h b/libraries/task/src/task/Task.h index 6979815cd2..60ccd26b70 100644 --- a/libraries/task/src/task/Task.h +++ b/libraries/task/src/task/Task.h @@ -15,20 +15,15 @@ #include "Config.h" #include "Varying.h" -#include "SettingHandle.h" - -#include -#include - namespace task { class JobConcept; -template class JobT; -template class TaskT; +template class JobT; +template class TaskT; class JobNoIO {}; // Task Flow control class is a simple per value object used to communicate flow control commands trhough the graph of tasks. -// From within the Job::Run function, you can access it from the JobCOntext and issue commands which will be picked up by the Task calling for the Job run. +// From within the Job::Run function, you can access it from the JobContext and issue commands which will be picked up by the Task calling for the Job run. // This is first introduced to provide a way to abort all the work from within a task job. see the "abortTask" call class TaskFlow { public: @@ -55,11 +50,10 @@ protected: // The JobContext can be derived to add more global state to it that Jobs can access class JobContext { public: - JobContext(const QLoggingCategory& category); + JobContext(); virtual ~JobContext(); std::shared_ptr jobConfig { nullptr }; - const QLoggingCategory& profileCategory; // Task flow control TaskFlow taskFlow{}; @@ -115,10 +109,11 @@ template void jobRun(T& data, const JC& jo data.run(jobContext, input, output); } -template +template class Job { public: using Context = JC; + using TimeProfiler = TP; using ContextPointer = std::shared_ptr; using Config = JobConfig; using None = JobNoIO; @@ -162,7 +157,7 @@ public: void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); + TimeProfiler probe(("configure::" + JobConcept::getName())); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); } @@ -185,13 +180,12 @@ public: const Varying getInput() const { return _concept->getInput(); } const Varying getOutput() const { return _concept->getOutput(); } - template void feedInput(const I& in) { _concept->editInput().template edit() = in; } - - template void feedInput(int index, const S& inS) { (_concept->editInput().template editN(index)).template edit() = inS; } - QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); } void applyConfiguration() { return _concept->applyConfiguration(); } + template void feedInput(const I& in) { _concept->editInput().template edit() = in; } + template void feedInput(int index, const S& inS) { (_concept->editInput().template editN(index)).template edit() = inS; } + template T& edit() { auto concept = std::static_pointer_cast(_concept); assert(concept); @@ -205,14 +199,9 @@ public: } virtual void run(const ContextPointer& jobContext) { - PerformanceTimer perfTimer(getName().c_str()); - // NOTE: rather than use the PROFILE_RANGE macro, we create a Duration manually - Duration profileRange(jobContext->profileCategory, ("run::" + getName()).c_str()); - + TimeProfiler probe(getName()); auto startTime = std::chrono::high_resolution_clock::now(); - _concept->run(jobContext); - _concept->setCPURunTime((std::chrono::high_resolution_clock::now() - startTime)); } @@ -228,13 +217,14 @@ protected: // The build method is where child Jobs can be added internally to the task // where the input of the task can be setup to feed the child jobs // and where the output of the task is defined -template -class Task : public Job { +template +class Task : public Job { public: using Context = JC; + using TimeProfiler = TP; using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using JobType = Job; + using JobType = Job; using None = typename JobType::None; using Concept = typename JobType::Concept; using ConceptPointer = typename JobType::ConceptPointer; @@ -305,7 +295,7 @@ public: auto model = std::make_shared(name, input, std::make_shared()); { - Duration profileRange(trace_render(), ("build::" + model->getName()).c_str()); + TimeProfiler probe("build::" + model->getName()); model->_data.build(*(model), model->_input, model->_output, std::forward(args)...); } // Recreate the Config to use the templated type @@ -340,7 +330,7 @@ public: } void applyConfiguration() override { - Duration profileRange(trace_render(), ("configure::" + JobConcept::getName()).c_str()); + TimeProfiler probe("configure::" + JobConcept::getName()); jobConfigure(_data, *std::static_pointer_cast(Concept::_config)); for (auto& job : TaskConcept::_jobs) { job.applyConfiguration(); @@ -381,21 +371,20 @@ public: protected: }; -template -class Engine : public Task { +template +class Engine : public Task { public: using Context = JC; using ContextPointer = std::shared_ptr; using Config = TaskConfig; - using TaskType = Task; + + using TaskType = Task; using ConceptPointer = typename TaskType::ConceptPointer; - Engine(ConceptPointer concept) : TaskType(concept) {} + Engine(const ConceptPointer& concept, const ContextPointer& context) : TaskType(concept), _context(context) {} ~Engine() = default; - void reset(const ContextPointer& context) { - _context = context; - } + void reset(const ContextPointer& context) { _context = context; } void run() { if (_context) { @@ -407,18 +396,19 @@ protected: void run(const ContextPointer& jobContext) override { TaskType::run(_context); } - + ContextPointer _context; }; + } -#define Task_DeclareTypeAliases(ContextType) \ +#define Task_DeclareTypeAliases(ContextType, TimeProfiler) \ using JobConfig = task::JobConfig; \ using TaskConfig = task::TaskConfig; \ template using PersistentConfig = task::PersistentConfig; \ - using Job = task::Job; \ - using Task = task::Task; \ - using _Engine = task::Engine; \ + using Job = task::Job; \ + using Task = task::Task; \ + using Engine = task::Engine; \ using Varying = task::Varying; \ template < typename T0, typename T1 > using VaryingSet2 = task::VaryingSet2; \ template < typename T0, typename T1, typename T2 > using VaryingSet3 = task::VaryingSet3; \ @@ -429,4 +419,16 @@ protected: template < typename T0, typename T1, typename T2, typename T3, typename T4, typename T5, typename T6, typename T7 > using VaryingSet8 = task::VaryingSet8; \ template < class T, int NUM > using VaryingArray = task::VaryingArray; + + +#include +#include + +#define Task_DeclareCategoryTimeProfilerClass(className, category) \ + class className : public PerformanceTimer { \ + public: \ + className(const std::string& label) : PerformanceTimer(label.c_str()), profileRange(category(), label.c_str()) {} \ + Duration profileRange; \ + }; + #endif // hifi_task_Task_h diff --git a/libraries/workload/src/workload/Engine.cpp b/libraries/workload/src/workload/Engine.cpp index b3568758ef..fcce6025df 100644 --- a/libraries/workload/src/workload/Engine.cpp +++ b/libraries/workload/src/workload/Engine.cpp @@ -14,6 +14,6 @@ #include namespace workload { - WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {} + WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(), _space(space) {} } // namespace workload diff --git a/libraries/workload/src/workload/Engine.h b/libraries/workload/src/workload/Engine.h index 0700080dc8..7df8d8dd1a 100644 --- a/libraries/workload/src/workload/Engine.h +++ b/libraries/workload/src/workload/Engine.h @@ -32,8 +32,11 @@ namespace workload { }; using WorkloadContextPointer = std::shared_ptr; - Task_DeclareTypeAliases(WorkloadContext) - using Engine = _Engine; + + Task_DeclareCategoryTimeProfilerClass(WorkloadTimeProfiler, trace_workload); + + // Instanciate the specialized types of Job Engine and Task for the Workload context + Task_DeclareTypeAliases(WorkloadContext, WorkloadTimeProfiler) using EnginePointer = std::shared_ptr; } // namespace workload diff --git a/scripts/developer/utilities/lib/jet/jet.js b/scripts/developer/utilities/lib/jet/jet.js index 39da9b6d90..85842b8861 100644 --- a/scripts/developer/utilities/lib/jet/jet.js +++ b/scripts/developer/utilities/lib/jet/jet.js @@ -12,15 +12,15 @@ // traverse task tree function task_traverse(root, functor, depth) { - // if (root.isTask()) { - depth++; + if (root.isTask()) { + depth++; for (var i = 0; i 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + node.append(newItem) + jobTreePath.push(0); + } else if (jobTreePath.length >= depth) { + var node = jobsRoot; + for (var n = 0; n < (depth - 1); n++) { + newItem.path += (n > 0 ? "." : "") + node.get(jobTreePath[n]).name + node = node.get(jobTreePath[n]).subNode + } + node.append(newItem) + jobTreePath[depth-1] = index; + while (jobTreePath.length > depth) { + jobTreePath.pop(); + } + } + } + return true; + } + + Jet.task_traverseTree(rootConfig, functor); + } + + + ListModel { + id: jobsModel + } + + Component { + id: objRecursiveDelegate + Column { + id: objRecursiveColumn + clip: true + visible: model.init + + MouseArea { + width: objRow.implicitWidth + height: objRow.implicitHeight + onDoubleClicked: { + for(var i = 1; i < parent.children.length - 1; ++i) { + parent.children[i].visible = !parent.children[i].visible + } + } + Row { + id: objRow + Item { + height: 1 + width: model.level * 15 + } + HifiControls.CheckBox { + property var config: root.rootConfig.getConfig(model.path + "." + model.name); + text: (objRecursiveColumn.children.length > 2 ? + objRecursiveColumn.children[1].visible ? + qsTr("- ") : qsTr("+ ") : qsTr(" ")) + model.name + " ms=" + config.cpuRunTime.toFixed(2) + checked: config.enabled + } + } + } + Repeater { + model: subNode + delegate: objRecursiveDelegate + } + } + } + + Original.ScrollView { + anchors.fill: parent + ListView { + id: theView + model: jobsModel + delegate: objRecursiveDelegate + } + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/lib/jet/qml/qmldir b/scripts/developer/utilities/lib/jet/qml/qmldir index f926d8cc67..2df22caa6a 100644 --- a/scripts/developer/utilities/lib/jet/qml/qmldir +++ b/scripts/developer/utilities/lib/jet/qml/qmldir @@ -1 +1,2 @@ -TaskList 1.0 TaskList.qml \ No newline at end of file +TaskList 1.0 TaskList.qml +TaskViewList 1.0 TaskViewList.qml diff --git a/scripts/developer/utilities/render/deferredLighting.qml b/scripts/developer/utilities/render/deferredLighting.qml index 874eddc9ca..8a4a8f0622 100644 --- a/scripts/developer/utilities/render/deferredLighting.qml +++ b/scripts/developer/utilities/render/deferredLighting.qml @@ -37,9 +37,9 @@ Rectangle { anchors.left: parent.left anchors.right: parent.right - spacing: 20 + spacing: 5 Column { - spacing: 10 + spacing: 5 // padding: 10 Repeater { model: [ @@ -62,7 +62,7 @@ Rectangle { Column { - spacing: 10 + spacing: 5 Repeater { model: [ "Obscurance:LightingModel:enableObscurance", @@ -82,7 +82,7 @@ Rectangle { } Column { - spacing: 10 + spacing: 5 Repeater { model: [ "Ambient:LightingModel:enableAmbientLight", @@ -106,7 +106,7 @@ Rectangle { Column { anchors.left: parent.left anchors.right: parent.right - spacing: 10 + spacing: 5 Repeater { model: [ "Tone Mapping Exposure:ToneMapping:exposure:5.0:-5.0" ] @@ -212,9 +212,9 @@ Rectangle { Separator {} Row { - spacing: 10 + spacing: 5 Column { - spacing: 10 + spacing: 5 HifiControls.CheckBox { boxSize: 20 @@ -255,7 +255,7 @@ Rectangle { } Column { - spacing: 10 + spacing: 5 HifiControls.CheckBox { boxSize: 20 text: "Metas" @@ -277,14 +277,12 @@ Rectangle { } } Separator {} - - Jet.TaskList { - rootConfig: Render - anchors.left: parent.left - anchors.right: parent.right - - height: 200 + HifiControls.Button { + text: "Engine" + // activeFocusOnPress: false + onClicked: { + sendToScript({method: "openEngineView"}); + } } } - //} } diff --git a/scripts/developer/utilities/render/engineInspector.js b/scripts/developer/utilities/render/engineInspector.js new file mode 100644 index 0000000000..dcf13157b5 --- /dev/null +++ b/scripts/developer/utilities/render/engineInspector.js @@ -0,0 +1,13 @@ + function openEngineTaskView() { + // Set up the qml ui + var qml = Script.resolvePath('engineInspector.qml'); + var window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + //window.closed.connect(function() { Script.stop(); }); + } + openEngineTaskView(); \ No newline at end of file diff --git a/scripts/developer/utilities/render/engineInspector.qml b/scripts/developer/utilities/render/engineInspector.qml new file mode 100644 index 0000000000..1b9941e64e --- /dev/null +++ b/scripts/developer/utilities/render/engineInspector.qml @@ -0,0 +1,30 @@ +// +// deferredLighting.qml +// +// Created by Sam Gateau on 6/6/2016 +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or https://www.apache.org/licenses/LICENSE-2.0.html +// +import QtQuick 2.7 +import QtQuick.Controls 1.4 +import QtQuick.Layouts 1.3 + +import "qrc:///qml/styles-uit" +import "qrc:///qml/controls-uit" as HifiControls + +import "../lib/jet/qml" as Jet + +Item { + HifiConstants { id: hifi;} + id: render; + anchors.fill: parent + + property var mainViewTask: Render.getConfig("RenderMainView") + + Jet.TaskListView { + rootConfig: Render + anchors.fill: render + } +} \ No newline at end of file diff --git a/scripts/developer/utilities/render/luci.js b/scripts/developer/utilities/render/luci.js index 6482c884ff..005d96780a 100644 --- a/scripts/developer/utilities/render/luci.js +++ b/scripts/developer/utilities/render/luci.js @@ -64,9 +64,6 @@ button.editProperties({isActive: onLuciScreen}); wireEventBridge(onLuciScreen); } - - function fromQml(message) { - } button.clicked.connect(onClicked); tablet.screenChanged.connect(onScreenChanged); @@ -82,14 +79,6 @@ Controller.mouseMoveEvent.connect(function (e) { if (moveDebugCursor) setDebugCursor(e.x, e.y); }); - Script.scriptEnding.connect(function () { - if (onLuciScreen) { - tablet.gotoHomeScreen(); - } - button.clicked.disconnect(onClicked); - tablet.screenChanged.disconnect(onScreenChanged); - tablet.removeButton(button); - }); function setDebugCursor(x, y) { nx = (x / Window.innerWidth); @@ -98,4 +87,46 @@ Render.getConfig("RenderMainView").getConfig("Antialiasing").debugCursorTexcoord = { x: nx, y: ny }; } + + function fromQml(message) { + switch (message.method) { + case "openEngineView": + openEngineTaskView(); + break; + } + } + + + var engineInspectorView = null + function openEngineTaskView() { + if (engineInspectorView == null) { + var qml = Script.resolvePath('engineInspector.qml'); + var window = new OverlayWindow({ + title: 'Render Engine', + source: qml, + width: 300, + height: 400 + }); + window.setPosition(200, 50); + engineInspectorView = window + window.closed.connect(function() { engineInspectorView = null; }); + } else { + engineInspectorView.setPosition(200, 50); + } + } + + + + Script.scriptEnding.connect(function () { + if (onLuciScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + + if (engineInspectorView !== null) { + engineInspectorView.close() + } + }); }()); \ No newline at end of file diff --git a/tests-manual/render-perf/src/main.cpp b/tests-manual/render-perf/src/main.cpp index 33aea6dcc9..7126b333f6 100644 --- a/tests-manual/render-perf/src/main.cpp +++ b/tests-manual/render-perf/src/main.cpp @@ -1107,7 +1107,7 @@ private: } } }; - render::EnginePointer _renderEngine { new render::Engine() }; + render::EnginePointer _renderEngine { new render::RenderEngine() }; render::ScenePointer _main3DScene { new render::Scene(glm::vec3(-0.5f * (float)TREE_SCALE), (float)TREE_SCALE) }; QSize _size; QSettings _settings; diff --git a/tools/auto-tester/src/ImageComparer.cpp b/tools/auto-tester/src/ImageComparer.cpp index 99f7d22c5f..eb892484a2 100644 --- a/tools/auto-tester/src/ImageComparer.cpp +++ b/tools/auto-tester/src/ImageComparer.cpp @@ -15,12 +15,6 @@ // Computes SSIM - see https://en.wikipedia.org/wiki/Structural_similarity // The value is computed for the luminance component and the average value is returned double ImageComparer::compareImages(QImage resultImage, QImage expectedImage) const { - // Make sure the image is 8 bits per colour - QImage::Format format = expectedImage.format(); - if (format != QImage::Format::Format_ARGB32) { - throw -1; - } - const int L = 255; // (2^number of bits per pixel) - 1 const double K1 { 0.01 }; const double K2 { 0.03 }; diff --git a/tools/auto-tester/src/Test.cpp b/tools/auto-tester/src/Test.cpp index 253f30a3b1..23d097b855 100644 --- a/tools/auto-tester/src/Test.cpp +++ b/tools/auto-tester/src/Test.cpp @@ -71,7 +71,7 @@ bool Test::compareImageLists(bool isInteractiveMode, QProgressBar* progressBar) QImage resultImage(resultImagesFullFilenames[i]); QImage expectedImage(expectedImagesFullFilenames[i]); - if (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height()) { + if (isInteractiveMode && (resultImage.width() != expectedImage.width() || resultImage.height() != expectedImage.height())) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Images are not the same size"); exit(-1); } @@ -131,7 +131,7 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai exit(-1); } - QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) }; + QString failureFolderPath { testResultsFolderPath + "/" + "Failure_" + QString::number(index) + "--" + testFailure._actualImageFilename.left(testFailure._actualImageFilename.length() - 4) }; if (!QDir().mkdir(failureFolderPath)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to create folder " + failureFolderPath); exit(-1); @@ -158,20 +158,20 @@ void Test::appendTestResultsToFile(const QString& testResultsFolderPath, TestFai QString destinationFile; sourceFile = testFailure._pathname + testFailure._expectedImageFilename; - destinationFile = failureFolderPath + "/" + "Expected Image.jpg"; + destinationFile = failureFolderPath + "/" + "Expected Image.png"; if (!QFile::copy(sourceFile, destinationFile)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } sourceFile = testFailure._pathname + testFailure._actualImageFilename; - destinationFile = failureFolderPath + "/" + "Actual Image.jpg"; + destinationFile = failureFolderPath + "/" + "Actual Image.png"; if (!QFile::copy(sourceFile, destinationFile)) { QMessageBox::critical(0, "Internal error: " + QString(__FILE__) + ":" + QString::number(__LINE__), "Failed to copy " + sourceFile + " to " + destinationFile); exit(-1); } - comparisonImage.save(failureFolderPath + "/" + "Difference Image.jpg"); + comparisonImage.save(failureFolderPath + "/" + "Difference Image.png"); } void Test::startTestsEvaluation(const QString& testFolder) { @@ -248,7 +248,7 @@ void Test::startTestsEvaluation(const QString& testFolder) { void Test::finishTestsEvaluation(bool isRunningFromCommandline, bool interactiveMode, QProgressBar* progressBar) { bool success = compareImageLists((!isRunningFromCommandline && interactiveMode), progressBar); - if (!isRunningFromCommandline) { + if (interactiveMode && !isRunningFromCommandline) { if (success) { QMessageBox::information(0, "Success", "All images are as expected"); } else { @@ -295,7 +295,7 @@ QString Test::extractPathFromTestsDown(const QString& fullPath) { return partialPath; } -void Test::importTest(QTextStream& textStream, const QString& testPathname) { +void Test::includeTest(QTextStream& textStream, const QString& testPathname) { QString partialPath = extractPathFromTestsDown(testPathname); textStream << "Script.include(\"" << "https://github.com/" << GIT_HUB_USER << "/hifi_tests/blob/" << GIT_HUB_BRANCH @@ -329,24 +329,24 @@ void Test::createRecursiveScript() { // This method creates a `testRecursive.js` script in every sub-folder. void Test::createAllRecursiveScripts() { // Select folder to start recursing from - QString previousSelection = testDirectory; + QString previousSelection = testsRootDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts", + testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the recursive scripts", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (testsRootDirectory == "") { + testsRootDirectory = previousSelection; return; } - createRecursiveScript(testDirectory, false); + createRecursiveScript(testsRootDirectory, false); - QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories); + QDirIterator it(testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); while (it.hasNext()) { QString directory = it.next(); @@ -395,22 +395,31 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact const QString DATE_TIME_FORMAT("MMM d yyyy, h:mm"); textStream << "// This is an automatically generated file, created by auto-tester on " << QDateTime::currentDateTime().toString(DATE_TIME_FORMAT) << endl << endl; + textStream << "user = \"" + GIT_HUB_USER + "/\"" << endl; + textStream << "repository = \"" + GIT_HUB_REPOSITORY + "/\"" << endl; + textStream << "branch = \"" + GIT_HUB_BRANCH + "/\"" << endl << endl; + textStream << "var autoTester = Script.require(\"https://github.com/" + GIT_HUB_USER + "/hifi_tests/blob/" + GIT_HUB_BRANCH + "/tests/utils/autoTester.js?raw=true\");" << endl << endl; textStream << "autoTester.enableRecursive();" << endl; textStream << "autoTester.enableAuto();" << endl << endl; - QVector testPathnames; + // This is used to verify that the recursive test contains at least one test + bool testFound{ false }; + + // Directories are included in reverse order. The autoTester scripts use a stack mechanism, + // so this ensures that the tests run in alphabetical order (a convenience when debugging) + QStringList directories; // First test if top-level folder has a test.js file const QString testPathname{ topLevelDirectory + "/" + TEST_FILENAME }; QFileInfo fileInfo(testPathname); if (fileInfo.exists()) { // Current folder contains a test - importTest(textStream, testPathname); + directories.push_front(testPathname); - testPathnames << testPathname; + testFound = true; } QDirIterator it(topLevelDirectory.toStdString().c_str(), QDirIterator::Subdirectories); @@ -427,18 +436,23 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact QFileInfo fileInfo(testPathname); if (fileInfo.exists()) { // Current folder contains a test - importTest(textStream, testPathname); + directories.push_front(testPathname); - testPathnames << testPathname; + testFound = true; } } - if (interactiveMode && testPathnames.length() <= 0) { + if (interactiveMode && !testFound) { QMessageBox::information(0, "Failure", "No \"" + TEST_FILENAME + "\" files found"); allTestsFilename.close(); return; } + // Now include the test scripts + for (int i = 0; i < directories.length(); ++i) { + includeTest(textStream, directories.at(i)); + } + textStream << endl; textStream << "autoTester.runRecursive();" << endl; @@ -449,7 +463,7 @@ void Test::createRecursiveScript(const QString& topLevelDirectory, bool interact } } -void Test::createTest() { +void Test::createTests() { // Rename files sequentially, as ExpectedResult_00000.jpeg, ExpectedResult_00001.jpg and so on // Any existing expected result images will be deleted QString previousSelection = snapshotDirectory; @@ -467,18 +481,18 @@ void Test::createTest() { return; } - previousSelection = testDirectory; + previousSelection = testsRootDirectory; parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select folder to save the test images", parent, + testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select test root folder", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (testsRootDirectory == "") { + testsRootDirectory = previousSelection; return; } @@ -493,8 +507,23 @@ void Test::createTest() { QMessageBox::critical(0, "Error", "More than " + QString::number(maxImages) + " images not supported"); exit(-1); } - QString newFilename = "ExpectedImage_" + QString::number(i - 1).rightJustified(5, '0') + ".png"; - QString fullNewFileName = testDirectory + "/" + newFilename; + + // Path to test is extracted from the file name + // Example: + // filename is tests.engine.interaction.pointer.laser.distanceScaleEnd.00000.jpg + // path is /engine/interaction/pointer/laser/distanceScaleEnd + // + // Note: we don't use the first part and the last 2 parts of the filename at this stage + // + QStringList pathParts = currentFilename.split("."); + QString fullNewFileName = testsRootDirectory; + for (int j = 1; j < pathParts.size() - 2; ++j) { + fullNewFileName += "/" + pathParts[j]; + } + + // The image index is the penultimate component of the path parts (the last being the file extension) + QString newFilename = "ExpectedImage_" + pathParts[pathParts.size() - 2].rightJustified(5, '0') + ".png"; + fullNewFileName += "/" + newFilename; try { copyJPGtoPNG(fullCurrentFilename, fullNewFileName); @@ -602,29 +631,29 @@ void Test::createMDFile() { void Test::createAllMDFiles() { // Select folder to start recursing from - QString previousSelection = testDirectory; + QString previousSelection = testsRootDirectory; QString parent = previousSelection.left(previousSelection.lastIndexOf('/')); if (!parent.isNull() && parent.right(1) != "/") { parent += "/"; } - testDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files", parent, + testsRootDirectory = QFileDialog::getExistingDirectory(nullptr, "Please select the root folder for the MD files", parent, QFileDialog::ShowDirsOnly); // If user cancelled then restore previous selection and return - if (testDirectory == "") { - testDirectory = previousSelection; + if (testsRootDirectory == "") { + testsRootDirectory = previousSelection; return; } // First test if top-level folder has a test.js file - const QString testPathname { testDirectory + "/" + TEST_FILENAME }; + const QString testPathname{ testsRootDirectory + "/" + TEST_FILENAME }; QFileInfo fileInfo(testPathname); if (fileInfo.exists()) { - createMDFile(testDirectory); + createMDFile(testsRootDirectory); } - QDirIterator it(testDirectory.toStdString().c_str(), QDirIterator::Subdirectories); + QDirIterator it(testsRootDirectory.toStdString().c_str(), QDirIterator::Subdirectories); while (it.hasNext()) { QString directory = it.next(); diff --git a/tools/auto-tester/src/Test.h b/tools/auto-tester/src/Test.h index 2fedc66959..32564035e7 100644 --- a/tools/auto-tester/src/Test.h +++ b/tools/auto-tester/src/Test.h @@ -44,7 +44,7 @@ public: void createAllRecursiveScripts(); void createRecursiveScript(const QString& topLevelDirectory, bool interactiveMode); - void createTest(); + void createTests(); void createMDFile(); void createAllMDFiles(); void createMDFile(const QString& topLevelDirectory); @@ -57,7 +57,7 @@ public: bool isInSnapshotFilenameFormat(const QString& imageFormat, const QString& filename); - void importTest(QTextStream& textStream, const QString& testPathname); + void includeTest(QTextStream& textStream, const QString& testPathname); void appendTestResultsToFile(const QString& testResultsFolderPath, TestFailure testFailure, QPixmap comparisonImage); @@ -91,8 +91,10 @@ private: // We have two directories to work with. // The first is the directory containing the test we are working with - // The second contains the snapshots taken for test runs that need to be evaluated + // The second is the root directory of all tests + // The third contains the snapshots taken for test runs that need to be evaluated QString testDirectory; + QString testsRootDirectory; QString snapshotDirectory; QStringList expectedImagesFilenames; @@ -101,8 +103,10 @@ private: // Used for accessing GitHub const QString GIT_HUB_USER{ "highfidelity" }; - const QString GIT_HUB_BRANCH { "master" }; - const QString DATETIME_FORMAT { "yyyy-MM-dd_hh-mm-ss" }; + const QString GIT_HUB_REPOSITORY{ "hifi_tests" }; + const QString GIT_HUB_BRANCH{ "master" }; + + const QString DATETIME_FORMAT{ "yyyy-MM-dd_hh-mm-ss" }; ExtractedText getTestScriptLines(QString testFileName); diff --git a/tools/auto-tester/src/ui/AutoTester.cpp b/tools/auto-tester/src/ui/AutoTester.cpp index db9974a250..ea2633edf4 100644 --- a/tools/auto-tester/src/ui/AutoTester.cpp +++ b/tools/auto-tester/src/ui/AutoTester.cpp @@ -40,8 +40,8 @@ void AutoTester::on_createAllRecursiveScriptsButton_clicked() { test->createAllRecursiveScripts(); } -void AutoTester::on_createTestButton_clicked() { - test->createTest(); +void AutoTester::on_createTestsButton_clicked() { + test->createTests(); } void AutoTester::on_createMDFileButton_clicked() { @@ -95,7 +95,7 @@ void AutoTester::saveImage(int index) { pixmap.loadFromData(downloaders[index]->downloadedData()); QImage image = pixmap.toImage(); - image = image.convertToFormat(QImage::Format_ARGB32); + image = image.convertToFormat(QImage::Format_RGB32); QString fullPathname = _directoryName + "/" + _filenames[index]; if (!image.save(fullPathname, 0, 100)) { diff --git a/tools/auto-tester/src/ui/AutoTester.h b/tools/auto-tester/src/ui/AutoTester.h index fe37f2298d..5991afed1b 100644 --- a/tools/auto-tester/src/ui/AutoTester.h +++ b/tools/auto-tester/src/ui/AutoTester.h @@ -32,7 +32,7 @@ private slots: void on_evaluateTestsButton_clicked(); void on_createRecursiveScriptButton_clicked(); void on_createAllRecursiveScriptsButton_clicked(); - void on_createTestButton_clicked(); + void on_createTestsButton_clicked(); void on_createMDFileButton_clicked(); void on_createAllMDFilesButton_clicked(); void on_createTestsOutlineButton_clicked(); diff --git a/tools/auto-tester/src/ui/AutoTester.ui b/tools/auto-tester/src/ui/AutoTester.ui index 8c534eb7c7..c9ea229012 100644 --- a/tools/auto-tester/src/ui/AutoTester.ui +++ b/tools/auto-tester/src/ui/AutoTester.ui @@ -27,7 +27,7 @@ Close - + 20 @@ -37,7 +37,7 @@ - Create Test + Create Tests