From 72649f5c06ba1820cc2ac24c5689291506591a9d Mon Sep 17 00:00:00 2001 From: samcake Date: Mon, 9 Apr 2018 17:27:40 -0700 Subject: [PATCH] More featuers for the view of the workload and test scrtpts to stress the system) --- interface/src/Application.cpp | 2 +- interface/src/workload/GameWorkload.cpp | 3 +- interface/src/workload/GameWorkload.h | 2 +- .../src/workload/GameWorkloadRenderer.cpp | 2 +- libraries/workload/src/workload/View.cpp | 8 +- libraries/workload/src/workload/View.h | 4 +- libraries/workload/src/workload/ViewTask.cpp | 22 +- libraries/workload/src/workload/ViewTask.h | 8 + .../workload/testSimulationWorkload.js | 92 +++++++++ .../workload/testSimulationWorkload.qml | 61 ++++++ .../workload/test_simulation_scene.js | 194 ++++++++++++++++++ .../utilities/workload/workloadInspector.qml | 26 ++- 12 files changed, 410 insertions(+), 14 deletions(-) create mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.js create mode 100644 scripts/developer/utilities/workload/testSimulationWorkload.qml create mode 100644 scripts/developer/utilities/workload/test_simulation_scene.js diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 394391807f..0445a0dbea 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4291,7 +4291,7 @@ void Application::idle() { } { - _gameWorkload.updateViews(_viewFrustum); + _gameWorkload.updateViews(_viewFrustum, getMyAvatar()->getHeadPosition()); _gameWorkload._engine->run(); } { diff --git a/interface/src/workload/GameWorkload.cpp b/interface/src/workload/GameWorkload.cpp index b6e26bcc48..0fc3e32701 100644 --- a/interface/src/workload/GameWorkload.cpp +++ b/interface/src/workload/GameWorkload.cpp @@ -48,8 +48,9 @@ void GameWorkload::shutdown() { _engine.reset(); } -void GameWorkload::updateViews(const ViewFrustum& frustum) { +void GameWorkload::updateViews(const ViewFrustum& frustum, const glm::vec3& headPosition) { workload::Views views; + views.emplace_back(workload::View::evalFromFrustum(frustum, headPosition - frustum.getPosition())); views.emplace_back(workload::View::evalFromFrustum(frustum)); _engine->feedInput(views); } diff --git a/interface/src/workload/GameWorkload.h b/interface/src/workload/GameWorkload.h index 01d748ba0e..023ecab1b8 100644 --- a/interface/src/workload/GameWorkload.h +++ b/interface/src/workload/GameWorkload.h @@ -37,7 +37,7 @@ public: const PhysicalEntitySimulationPointer& simulation); void shutdown(); - void updateViews(const ViewFrustum& frustum); + void updateViews(const ViewFrustum& frustum, const glm::vec3& headPosition); workload::EnginePointer _engine { std::make_shared() }; }; diff --git a/interface/src/workload/GameWorkloadRenderer.cpp b/interface/src/workload/GameWorkloadRenderer.cpp index c21f93d764..07b6ac23f0 100644 --- a/interface/src/workload/GameWorkloadRenderer.cpp +++ b/interface/src/workload/GameWorkloadRenderer.cpp @@ -66,7 +66,7 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, if (!render::Item::isValidID(_spaceRenderItemID)) { _spaceRenderItemID = scene->allocateID(); auto renderItem = std::make_shared(); - renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f); + renderItem->editBound().setBox(glm::vec3(0.0f), 32000.0f); renderItem->setAllProxies(proxies); transaction.resetItem(_spaceRenderItemID, std::make_shared(renderItem)); } diff --git a/libraries/workload/src/workload/View.cpp b/libraries/workload/src/workload/View.cpp index 3e27235f5f..3f002da36a 100644 --- a/libraries/workload/src/workload/View.cpp +++ b/libraries/workload/src/workload/View.cpp @@ -22,9 +22,13 @@ void View::setFov(float angleRad) { fov_halfAngle_tan_cos_sin.w = sinf(halfAngle); } -View View::evalFromFrustum(const ViewFrustum& frustum) { +void View::makeHorizontal() { + direction = glm::normalize(glm::vec3(direction.x, 0.0f, direction.z)); +} + +View View::evalFromFrustum(const ViewFrustum& frustum, const glm::vec3& offset) { View view; - view.origin = frustum.getPosition(); + view.origin = frustum.getPosition() + offset; view.direction = frustum.getDirection(); view.setFov(frustum.getFieldOfView()); diff --git a/libraries/workload/src/workload/View.h b/libraries/workload/src/workload/View.h index 5f2be465c3..430ac3a568 100644 --- a/libraries/workload/src/workload/View.h +++ b/libraries/workload/src/workload/View.h @@ -53,8 +53,10 @@ public: // Set fov properties from angle void setFov(float angleRad); + // Helper function to force the direction in the XZ plane + void makeHorizontal(); - static View evalFromFrustum(const ViewFrustum& frustum); + static View evalFromFrustum(const ViewFrustum& frustum, const glm::vec3& offset = glm::vec3()); static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance); static void updateRegions(View& view); diff --git a/libraries/workload/src/workload/ViewTask.cpp b/libraries/workload/src/workload/ViewTask.cpp index 705f517243..4ab4da5231 100644 --- a/libraries/workload/src/workload/ViewTask.cpp +++ b/libraries/workload/src/workload/ViewTask.cpp @@ -23,12 +23,30 @@ void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& i _views = inputs; } + // Filter the first view centerer on the avatar head if needed + Views usedViews; + if (_views.size() >= 2) { + if (data.useAvatarView) { + usedViews.push_back(_views[0]); + usedViews.insert(usedViews.end(), _views.begin() + 2, _views.end()); + } else { + usedViews.insert(usedViews.end(), _views.begin() + 1, _views.end()); + } + } else { + usedViews = _views; + } + + // Force frutum orientation horizontal if needed + if (usedViews.size() > 0 && data.forceViewHorizontal) { + usedViews[0].makeHorizontal(); + } + // Update regions based on the current config - for (auto& v : _views) { + for (auto& v : usedViews) { View::updateRegions(v, (float*) &data); } // Views are setup, assign to the Space - renderContext->_space->setViews(_views); + renderContext->_space->setViews(usedViews); } diff --git a/libraries/workload/src/workload/ViewTask.h b/libraries/workload/src/workload/ViewTask.h index 2b77aaf273..caba6260db 100644 --- a/libraries/workload/src/workload/ViewTask.h +++ b/libraries/workload/src/workload/ViewTask.h @@ -23,6 +23,8 @@ namespace workload { Q_PROPERTY(float r3Front READ getR3Front WRITE setR3Front NOTIFY dirty) Q_PROPERTY(float r3Back READ getR3Back WRITE setR3Back NOTIFY dirty) Q_PROPERTY(bool freezeViews READ getFreezeView WRITE setFreezeView NOTIFY dirty) + Q_PROPERTY(bool useAvatarView READ useAvatarView WRITE setUseAvatarView NOTIFY dirty) + Q_PROPERTY(bool forceViewHorizontal READ forceViewHorizontal WRITE setForceViewHorizontal NOTIFY dirty) public: @@ -42,6 +44,10 @@ namespace workload { bool getFreezeView() const { return data.freezeViews; } void setFreezeView(bool freeze) { data.freezeViews = freeze; emit dirty(); } + bool useAvatarView() const { return data.useAvatarView; } + void setUseAvatarView(bool use) { data.useAvatarView = use; emit dirty(); } + bool forceViewHorizontal() const { return data.forceViewHorizontal; } + void setForceViewHorizontal(bool use) { data.forceViewHorizontal = use; emit dirty(); } struct Data { float r1Back { 2.0f }; @@ -54,6 +60,8 @@ namespace workload { float r3Front{ 100.0f }; bool freezeViews{ false }; + bool useAvatarView{ false }; + bool forceViewHorizontal{ false }; } data; signals: diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.js b/scripts/developer/utilities/workload/testSimulationWorkload.js new file mode 100644 index 0000000000..b4eb66880c --- /dev/null +++ b/scripts/developer/utilities/workload/testSimulationWorkload.js @@ -0,0 +1,92 @@ +"use strict"; + +// +// testSimulationWorkload.js +// tablet-workload-engine test app +// +// Copyright 2018 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 +// +Script.include("./test_simulation_scene.js") + +(function() { + var TABLET_BUTTON_NAME = "Test Sim"; + var QMLAPP_URL = Script.resolvePath("./testSimulationWorkload.qml"); + var ICON_URL = Script.resolvePath("../../../system/assets/images/luci-i.svg"); + var ACTIVE_ICON_URL = Script.resolvePath("../../../system/assets/images/luci-a.svg"); + + var test = { scene:[] } + test.clearScene = function clearScene() { + for (var i = 0; i < this.scene.length; i++) { + Entities.deleteEntity(this.scene[i]); + } + } + + + var onAppScreen = false; + + function onClicked() { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } else { + tablet.loadQMLSource(QMLAPP_URL); + } + } + + var tablet = Tablet.getTablet("com.highfidelity.interface.tablet.system"); + var button = tablet.addButton({ + text: TABLET_BUTTON_NAME, + icon: ICON_URL, + activeIcon: ACTIVE_ICON_URL + }); + + var hasEventBridge = false; + + function wireEventBridge(on) { + if (!tablet) { + print("Warning in wireEventBridge(): 'tablet' undefined!"); + return; + } + if (on) { + if (!hasEventBridge) { + tablet.fromQml.connect(fromQml); + hasEventBridge = true; + } + } else { + if (hasEventBridge) { + tablet.fromQml.disconnect(fromQml); + hasEventBridge = false; + } + } + } + + function onScreenChanged(type, url) { + if (url === QMLAPP_URL) { + onAppScreen = true; + } else { + onAppScreen = false; + } + + button.editProperties({isActive: onAppScreen}); + wireEventBridge(onAppScreen); + } + + function fromQml(message) { + } + + button.clicked.connect(onClicked); + tablet.screenChanged.connect(onScreenChanged); + + Script.scriptEnding.connect(function () { + if (onAppScreen) { + tablet.gotoHomeScreen(); + } + button.clicked.disconnect(onClicked); + tablet.screenChanged.disconnect(onScreenChanged); + tablet.removeButton(button); + clearScene(); + }); + +}()); \ No newline at end of file diff --git a/scripts/developer/utilities/workload/testSimulationWorkload.qml b/scripts/developer/utilities/workload/testSimulationWorkload.qml new file mode 100644 index 0000000000..c71ea18a3d --- /dev/null +++ b/scripts/developer/utilities/workload/testSimulationWorkload.qml @@ -0,0 +1,61 @@ +// +// _workload.qml +// +// Created by Sam Gateau on 3/1/2018 +// Copyright 2018 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 "../render/configSlider" +import "./test_simulation_scene.js" as Sim + + +Rectangle { + HifiConstants { id: hifi;} + id: _test; + + width: parent ? parent.width : 400 + height: parent ? parent.height : 600 + anchors.margins: hifi.dimensions.contentMargin.x + + color: hifi.colors.baseGray; + + property var scene : [] + + function clearScene() { + for (var i = 0; i < _test.scene.length; i++) { + Entities.deleteEntity(_test.scene[i]); + } + } + Component.onCompleted: { + _test.scene = Sim.setupScene(); + + } + Component.onDestruction: { + clearScene() + } + + Column { + spacing: 5 + anchors.left: parent.left + anchors.right: parent.right + anchors.margins: hifi.dimensions.contentMargin.x + //padding: hifi.dimensions.contentMargin.x + + + + Separator {} + HifiControls.Label { + text: "Display" + } + Separator {} + + } +} diff --git a/scripts/developer/utilities/workload/test_simulation_scene.js b/scripts/developer/utilities/workload/test_simulation_scene.js new file mode 100644 index 0000000000..0517fce680 --- /dev/null +++ b/scripts/developer/utilities/workload/test_simulation_scene.js @@ -0,0 +1,194 @@ + +var DEFAULT_LIFETIME = 120; + +var GRID_WORLD_SIZE = 100.0; +var GRID_WORLD_RESOLUTION = 4.0; + +var BACKDROP_SIZE = GRID_WORLD_SIZE / GRID_WORLD_RESOLUTION; +var BACKDROP_HALFSIZE = BACKDROP_SIZE *0.5; +var BACKDROP_MIN_C = -2; + +var ROOT_Z_OFFSET = -3; +var ROOT_Y_OFFSET = -0.1; + +var TILE_UNIT = GRID_WORLD_RESOLUTION; +var TILE_DIM = { x: TILE_UNIT, y: TILE_UNIT, z: TILE_UNIT}; +var GRID_TILE_OFFSET = Vec3.multiply(0.5, TILE_DIM); + +var OBJECT_DIM = { x: 0.5, y: 0.5, z: 0.5}; + + +var shapeTypes = [ + "none", + "box", + "sphere", + "compound", + "simple-hull", + "simple-compound", + "static-mesh" +]; + +function getTileColor(a, b, c) { + var offset = (Math.abs(a) + ((Math.abs(b) + (Math.abs(c) % 2)) % 2)) % 2; + var intensity = (1 - offset) * 128 + offset * 255; + return { red: intensity * (a % 4), green: intensity, blue: intensity * (b % 4) }; +} + +function addObject(a, b, c, lifetime) { + var center = Vec3.sum(stageTileRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return (Entities.addEntity({ + type: "Shape", + shape: "Sphere", + name: "Backdrop", + color: getTileColor(a, b, c), + position: center, + rotation: stageOrientation, + dimensions: OBJECT_DIM, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + shapeType:shapeTypes[2], + dynamic: true, + gravity:{"x":0,"y":-9.8,"z":0}, + velocity:{"x":0,"y":0.02,"z":0}, + restitution:0.70, + friction:0.001, + damping:0.001, + + })); +} + +function addObjectGrid(backdrop, lifetime) { + for (var i = BACKDROP_HALFSIZE; i > -BACKDROP_HALFSIZE; i--) { + for (var j = -BACKDROP_HALFSIZE; j < BACKDROP_HALFSIZE; j++) { + backdrop.push(addObject(i, j, BACKDROP_MIN_C + 2, lifetime)); + } + } + +} + +function addFloor(lifetime) { + var floorDim = { x:BACKDROP_SIZE * TILE_DIM.x, y:TILE_DIM.y, z:BACKDROP_SIZE *TILE_DIM.x}; + var center = getStagePosOriAt(0, 0, -1).pos; + + return (Entities.addEntity({ + type: "Shape", + shape: "Cube", + name: "Floor", + color: { red: 20, green: 20, blue: 40 }, + position: center, + rotation: stageOrientation, + dimensions: floorDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + shapeType:shapeTypes[1], + // dynamic: true, + // gravity:{"x":0,"y":-9.8,"z":0}, + // velocity:{"x":0,"y":0.01,"z":0}, + restitution:0.999, + friction:0.000, + damping:0.0, + + })); +} + +function addZone(hasKeyLight, hasAmbient, lifetime) { + var zoneDim = Vec3.multiply(BACKDROP_SIZE, TILE_DIM); + var center = getStagePosOriAt(0, 0, 0).pos; + + var lightDir = Vec3.normalize(Vec3.sum(Vec3.multiply(-1, Quat.getUp(stageOrientation)), Vec3.multiply(-1, Quat.getRight(stageOrientation)))) + + return (Entities.addEntity({ + type: "Zone", + name: "Backdrop zone", + + position: center, + rotation: stageOrientation, + dimensions: zoneDim, + lifetime: (lifetime === undefined) ? DEFAULT_LIFETIME : lifetime, + + keyLightMode: "enabled", + skyboxMode: "enabled", + ambientLightMode: "enabled", + + keyLight:{ + intensity: 0.8 * hasKeyLight, + direction: { + "x": 0.037007175385951996, + "y": -0.7071067690849304, + "z": -0.7061376571655273 + }, + castShadows: true, + }, + ambientLight: { + ambientIntensity: 1.0 * hasAmbient, + ambientURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + }, + + hazeMode:"disabled", + backgroundMode:"skybox", + skybox:{ + color: {"red":2,"green":2,"blue":2}, // Dark grey background + skyboxURL: "https://github.com/highfidelity/hifi_tests/blob/master/assets/skymaps/Sky_Day-Sun-Mid-photo.ktx?raw=true", + } + })); +} + +function addTestScene(name, lifetime) { + var scene = []; + scene.push(addFloor(lifetime)); + scene.push(addZone(true, true, lifetime)); + + addObjectGrid(scene, lifetime); + + return scene; +} + + + +// Stage position and orientation initialised at setup +stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); +stageRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageTileRoot = {"x":0.0,"y":0.0,"z":0.0}; +stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); +stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); +stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + +setupScene = function (lifetime) { + MyAvatar.orientation = Quat.fromPitchYawRollDegrees(0.0, 0.0, 0.0); + var orientation = MyAvatar.orientation; + orientation = Quat.safeEulerAngles(orientation); + orientation.x = 0; + orientation = Quat.fromVec3Degrees(orientation); + + stageOrientation = orientation; + stageAxisA = Vec3.multiply(TILE_UNIT, Quat.getForward(stageOrientation)); + stageAxisB = Vec3.multiply(TILE_UNIT, Quat.getRight(stageOrientation)); + stageAxisC = Vec3.multiply(TILE_UNIT, Quat.getUp(stageOrientation)); + + stageRoot = Vec3.sum(MyAvatar.position, Vec3.multiply(-ROOT_Z_OFFSET, Quat.getForward(orientation))); + stageRoot = Vec3.sum(stageRoot, Vec3.multiply(ROOT_Y_OFFSET, Quat.getUp(orientation))); + stageTileRoot = Vec3.sum(stageRoot, GRID_TILE_OFFSET); + + return addTestScene("Physics_stage_backdrop", lifetime); +} + +getStagePosOriAt = function (a, b, c) { + var center = Vec3.sum(stageRoot, Vec3.multiply(a, stageAxisA)); + center = Vec3.sum(center, Vec3.multiply(b, stageAxisB)); + center = Vec3.sum(center, Vec3.multiply(c, stageAxisC)); + + return { "pos": center, "ori": stageOrientation}; +} + + +// var scene = setupScene(); + + +// clean up after test +/*Script.scriptEnding.connect(function () { + for (var i = 0; i < scene.length; i++) { + Entities.deleteEntity(scene[i]); + } +});*/ diff --git a/scripts/developer/utilities/workload/workloadInspector.qml b/scripts/developer/utilities/workload/workloadInspector.qml index ca8f11355a..bb3d290392 100644 --- a/scripts/developer/utilities/workload/workloadInspector.qml +++ b/scripts/developer/utilities/workload/workloadInspector.qml @@ -38,11 +38,27 @@ Rectangle { text: "Workload" } - HifiControls.CheckBox { - boxSize: 20 - text: "Freeze Views" - checked: Workload.getConfig("setupViews")["freezeViews"] - onCheckedChanged: { Workload.getConfig("SpaceToRender")["freezeViews"] = checked, Workload.getConfig("setupViews")["freezeViews"] = checked; } + RowLayout { + anchors.left: parent.left + anchors.right: parent.right + HifiControls.CheckBox { + boxSize: 20 + text: "Freeze Views" + checked: Workload.getConfig("setupViews")["freezeViews"] + onCheckedChanged: { Workload.getConfig("SpaceToRender")["freezeViews"] = checked, Workload.getConfig("setupViews")["freezeViews"] = checked; } + } + HifiControls.CheckBox { + boxSize: 20 + text: "Use Avatar View" + checked: Workload.getConfig("setupViews")["useAvatarView"] + onCheckedChanged: { Workload.getConfig("setupViews")["useAvatarView"] = checked; } + } + HifiControls.CheckBox { + boxSize: 20 + text: "force View Horizontal" + checked: Workload.getConfig("setupViews")["forceViewHorizontal"] + onCheckedChanged: { Workload.getConfig("setupViews")["forceViewHorizontal"] = checked; } + } } RowLayout {