diff --git a/interface/resources/meshes/images/default-image-model.fbx b/interface/resources/meshes/images/default-image-model.fbx index 641a7f82eb..781b01fb0f 100644 Binary files a/interface/resources/meshes/images/default-image-model.fbx and b/interface/resources/meshes/images/default-image-model.fbx differ diff --git a/interface/resources/qml/Stats.qml b/interface/resources/qml/Stats.qml index 4626d9bcda..a12bd4b2c0 100644 --- a/interface/resources/qml/Stats.qml +++ b/interface/resources/qml/Stats.qml @@ -257,7 +257,11 @@ Item { id: octreeCol spacing: 4; x: 4; y: 4; StatText { - text: "Engine: " + root.engineFrameTime.toFixed(1) + " ms" + text: "Render Engine: " + root.engineFrameTime.toFixed(1) + " ms" + } + StatText { + visible: root.expanded + text: root.renderEngineStats } StatText { text: "Batch: " + root.batchFrameTime.toFixed(1) + " ms" diff --git a/interface/resources/qml/hifi/AssetServer.qml b/interface/resources/qml/hifi/AssetServer.qml index 03d00fe773..19a559b66c 100644 --- a/interface/resources/qml/hifi/AssetServer.qml +++ b/interface/resources/qml/hifi/AssetServer.qml @@ -187,9 +187,10 @@ Windows.ScrollingWindow { var textures = JSON.stringify({ "tex.picture": defaultURL}); var shapeType = "box"; var dynamic = false; + var collisionless = true; var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); - Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, position, gravity); + Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, collisionless, position, gravity); } else { var SHAPE_TYPE_NONE = 0; var SHAPE_TYPE_SIMPLE_HULL = 1; @@ -234,6 +235,7 @@ Windows.ScrollingWindow { var result = JSON.parse(jsonResult); var url = result.textInput.trim(); var shapeType; + var collisionless = false; switch (result.comboBox) { case SHAPE_TYPE_SIMPLE_HULL: shapeType = "simple-hull"; @@ -252,6 +254,7 @@ Windows.ScrollingWindow { break; default: shapeType = "none"; + collisionless = true; } var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; @@ -273,7 +276,7 @@ Windows.ScrollingWindow { print("Asset browser - adding asset " + url + " (" + name + ") to world."); // Entities.addEntity doesn't work from QML, so we use this. - Entities.addModelEntity(name, url, "", shapeType, dynamic, addPosition, gravity); + Entities.addModelEntity(name, url, "", shapeType, dynamic, collisionless, addPosition, gravity); } } }); diff --git a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml index 503a3ccc17..0f70b44477 100644 --- a/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml +++ b/interface/resources/qml/hifi/dialogs/TabletAssetServer.qml @@ -144,7 +144,7 @@ Rectangle { } function canAddToWorld(path) { - var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i]; + var supportedExtensions = [/\.fbx\b/i, /\.obj\b/i, /\.jpg\b/i, /\.png\b/i]; if (selectedItemCount > 1) { return false; @@ -188,9 +188,10 @@ Rectangle { var textures = JSON.stringify({ "tex.picture": defaultURL}); var shapeType = "box"; var dynamic = false; + var collisionless = true; var position = Vec3.sum(MyAvatar.position, Vec3.multiply(2, Quat.getForward(MyAvatar.orientation))); var gravity = Vec3.multiply(Vec3.fromPolar(Math.PI / 2, 0), 0); - Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, position, gravity); + Entities.addModelEntity(name, modelURL, textures, shapeType, dynamic, collisionless, position, gravity); } else { var SHAPE_TYPE_NONE = 0; var SHAPE_TYPE_SIMPLE_HULL = 1; @@ -235,6 +236,7 @@ Rectangle { var result = JSON.parse(jsonResult); var url = result.textInput.trim(); var shapeType; + var collisionless = false; switch (result.comboBox) { case SHAPE_TYPE_SIMPLE_HULL: shapeType = "simple-hull"; @@ -253,6 +255,7 @@ Rectangle { break; default: shapeType = "none"; + collisionless = true; } var dynamic = result.checkBox !== null ? result.checkBox : DYNAMIC_DEFAULT; @@ -274,7 +277,7 @@ Rectangle { print("Asset browser - adding asset " + url + " (" + name + ") to world."); // Entities.addEntity doesn't work from QML, so we use this. - Entities.addModelEntity(name, url, "", shapeType, dynamic, addPosition, gravity); + Entities.addModelEntity(name, url, "", shapeType, dynamic, collisionless, addPosition, gravity); } } }); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index af159263ed..34cdf3cda8 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -6677,8 +6677,8 @@ void Application::addAssetToWorldSetMapping(QString filePath, QString mapping, Q addAssetToWorldError(filenameFromPath(filePath), errorInfo); } else { // to prevent files that aren't models from being loaded into world automatically - if (filePath.endsWith(OBJ_EXTENSION) || filePath.endsWith(FBX_EXTENSION) || - filePath.endsWith(JPG_EXTENSION) || filePath.endsWith(PNG_EXTENSION)) { + if (filePath.toLower().endsWith(OBJ_EXTENSION) || filePath.toLower().endsWith(FBX_EXTENSION) || + filePath.toLower().endsWith(JPG_EXTENSION) || filePath.toLower().endsWith(PNG_EXTENSION)) { addAssetToWorldAddEntity(filePath, mapping); } else { qCDebug(interfaceapp) << "Zipped contents are not supported entity files"; @@ -6695,7 +6695,7 @@ void Application::addAssetToWorldAddEntity(QString filePath, QString mapping) { EntityItemProperties properties; properties.setType(EntityTypes::Model); properties.setName(mapping.right(mapping.length() - 1)); - if (filePath.endsWith(PNG_EXTENSION) || filePath.endsWith(JPG_EXTENSION)) { + if (filePath.toLower().endsWith(PNG_EXTENSION) || filePath.toLower().endsWith(JPG_EXTENSION)) { QJsonObject textures { {"tex.picture", QString("atp:" + mapping) } }; @@ -6791,7 +6791,9 @@ void Application::addAssetToWorldCheckModelSize() { EntityItemProperties properties; properties.setDimensions(dimensions); properties.setVisible(true); - properties.setCollisionless(false); + if (!name.toLower().endsWith(PNG_EXTENSION) && !name.toLower().endsWith(JPG_EXTENSION)) { + properties.setCollisionless(false); + } properties.setUserData(GRABBABLE_USER_DATA); properties.setLastEdited(usecTimestampNow()); entityScriptingInterface->editEntity(entityID, properties); diff --git a/interface/src/ui/Stats.cpp b/interface/src/ui/Stats.cpp index 80f57bfe0e..ff42ed09e7 100644 --- a/interface/src/ui/Stats.cpp +++ b/interface/src/ui/Stats.cpp @@ -482,7 +482,7 @@ void Stats::updateStats(bool force) { float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; _gameUpdateStats = QString("/idle/update = %1 ms").arg(dt); - QVector categories = { "devices", "physics", "otherAvatars", "MyAvatar", "misc" }; + QVector categories = { "devices", "physics", "otherAvatars", "MyAvatar", "pickManager", "postUpdateLambdas", "misc" }; for (int32_t j = 0; j < categories.size(); ++j) { QString recordKey = "/idle/update/" + categories[j]; itr = allRecords.find(recordKey); @@ -502,10 +502,39 @@ void Stats::updateStats(bool force) { _gameUpdateStats = ""; emit gameUpdateStatsChanged(); } + + itr = allRecords.find("/paintGL/display/EngineRun/Engine"); + std::priority_queue renderEngineStats; + if (itr != allRecords.end()) { + float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; + _renderEngineStats = QString("/render = %1 ms").arg(dt); + + QVector categories = { "RenderMainView", "SecondaryCameraJob", "UpdateScene"}; + for (int32_t j = 0; j < categories.size(); ++j) { + QString recordKey = "/paintGL/display/EngineRun/Engine/" + categories[j]; + itr = allRecords.find(recordKey); + if (itr != allRecords.end()) { + float dt = (float)itr.value().getMovingAverage() / (float)USECS_PER_MSEC; + QString message = QString("\n %1 = %2").arg(categories[j]).arg(dt); + renderEngineStats.push(SortableStat(message, dt)); + } + } + while (!renderEngineStats.empty()) { + SortableStat stat = renderEngineStats.top(); + _renderEngineStats += stat.message; + renderEngineStats.pop(); + } + emit renderEngineStatsChanged(); + } else if (_renderEngineStats != "") { + _renderEngineStats = ""; + emit renderEngineStatsChanged(); + } } else if (_showGameUpdateStats) { _showGameUpdateStats = false; _gameUpdateStats = ""; + _renderEngineStats = ""; emit gameUpdateStatsChanged(); + emit renderEngineStatsChanged(); } } diff --git a/interface/src/ui/Stats.h b/interface/src/ui/Stats.h index af3189f20b..e5fc0beaf6 100644 --- a/interface/src/ui/Stats.h +++ b/interface/src/ui/Stats.h @@ -106,6 +106,7 @@ class Stats : public QQuickItem { STATS_PROPERTY(QString, lodStatus, QString()) STATS_PROPERTY(QString, timingStats, QString()) STATS_PROPERTY(QString, gameUpdateStats, QString()) + STATS_PROPERTY(QString, renderEngineStats, QString()) STATS_PROPERTY(int, serverElements, 0) STATS_PROPERTY(int, serverInternal, 0) STATS_PROPERTY(int, serverLeaves, 0) @@ -239,6 +240,7 @@ signals: void localLeavesChanged(); void timingStatsChanged(); void gameUpdateStatsChanged(); + void renderEngineStatsChanged(); void glContextSwapchainMemoryChanged(); void qmlTextureMemoryChanged(); void texturePendingTransfersChanged(); diff --git a/libraries/entities/src/EntityScriptingInterface.cpp b/libraries/entities/src/EntityScriptingInterface.cpp index 2b44b47128..93cbe781be 100644 --- a/libraries/entities/src/EntityScriptingInterface.cpp +++ b/libraries/entities/src/EntityScriptingInterface.cpp @@ -304,8 +304,9 @@ QUuid EntityScriptingInterface::addEntity(const EntityItemProperties& properties } } -QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, - bool dynamic, const glm::vec3& position, const glm::vec3& gravity) { +QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, + const QString& shapeType, bool dynamic, bool collisionless, + const glm::vec3& position, const glm::vec3& gravity) { _activityTracking.addedEntityCount++; EntityItemProperties properties; @@ -314,6 +315,7 @@ QUuid EntityScriptingInterface::addModelEntity(const QString& name, const QStrin properties.setModelURL(modelUrl); properties.setShapeTypeFromString(shapeType); properties.setDynamic(dynamic); + properties.setCollisionless(collisionless); properties.setPosition(position); properties.setGravity(gravity); if (!textures.isEmpty()) { diff --git a/libraries/entities/src/EntityScriptingInterface.h b/libraries/entities/src/EntityScriptingInterface.h index cdb784ffa8..6b4cd81e44 100644 --- a/libraries/entities/src/EntityScriptingInterface.h +++ b/libraries/entities/src/EntityScriptingInterface.h @@ -165,7 +165,7 @@ public slots: /// temporary method until addEntity can be used from QJSEngine /// Deliberately not adding jsdoc, only used internally. Q_INVOKABLE QUuid addModelEntity(const QString& name, const QString& modelUrl, const QString& textures, const QString& shapeType, bool dynamic, - const glm::vec3& position, const glm::vec3& gravity); + bool collisionless, const glm::vec3& position, const glm::vec3& gravity); /**jsdoc * Return the properties for the specified {EntityID}. diff --git a/scripts/system/edit.js b/scripts/system/edit.js index 0e1718ac45..5e9aefcb07 100644 --- a/scripts/system/edit.js +++ b/scripts/system/edit.js @@ -565,11 +565,12 @@ var toolBar = (function () { createNewEntity({ type: "Model", dimensions: { - x: 4.16, - y: 0.02, - z: 2.58 + x: 0.5385, + y: 0.2819, + z: 0.0092 }, shapeType: "box", + collisionless: true, modelURL: IMAGE_MODEL, textures: JSON.stringify({ "tex.picture": DEFAULT_IMAGE }) });