mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 19:59:28 +02:00
Merge pull request #6365 from sethalves/rework-visual-physics-debug
grab fix + physics logging/debug changes
This commit is contained in:
commit
b795b66b35
48 changed files with 692 additions and 274 deletions
|
@ -17,6 +17,7 @@
|
||||||
#include "OctreeSendThread.h"
|
#include "OctreeSendThread.h"
|
||||||
#include "OctreeServer.h"
|
#include "OctreeServer.h"
|
||||||
#include "OctreeServerConsts.h"
|
#include "OctreeServerConsts.h"
|
||||||
|
#include "OctreeLogging.h"
|
||||||
|
|
||||||
quint64 startSceneSleepTime = 0;
|
quint64 startSceneSleepTime = 0;
|
||||||
quint64 endSceneSleepTime = 0;
|
quint64 endSceneSleepTime = 0;
|
||||||
|
@ -572,14 +573,12 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
||||||
OctreeServer::trackInsideTime((float)elapsedInsideUsecs);
|
OctreeServer::trackInsideTime((float)elapsedInsideUsecs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
||||||
qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval
|
qCDebug(octree) << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval
|
||||||
<< " maxPacketsPerInterval = " << maxPacketsPerInterval
|
<< " maxPacketsPerInterval = " << maxPacketsPerInterval
|
||||||
<< " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval;
|
<< " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// Here's where we can/should allow the server to send other data...
|
// Here's where we can/should allow the server to send other data...
|
||||||
// send the environment packet
|
// send the environment packet
|
||||||
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
// TODO: should we turn this into a while loop to better handle sending multiple special packets
|
||||||
|
|
|
@ -506,6 +506,7 @@ Grabber.prototype.activateEntity = function(entityID, grabbedProperties) {
|
||||||
if (data["refCount"] == 1) {
|
if (data["refCount"] == 1) {
|
||||||
data["gravity"] = grabbedProperties.gravity;
|
data["gravity"] = grabbedProperties.gravity;
|
||||||
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
|
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
|
||||||
|
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
|
||||||
var whileHeldProperties = {gravity: {x:0, y:0, z:0}};
|
var whileHeldProperties = {gravity: {x:0, y:0, z:0}};
|
||||||
if (invertSolidWhileHeld) {
|
if (invertSolidWhileHeld) {
|
||||||
whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions;
|
whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions;
|
||||||
|
@ -522,7 +523,8 @@ Grabber.prototype.deactivateEntity = function(entityID) {
|
||||||
if (data["refCount"] < 1) {
|
if (data["refCount"] < 1) {
|
||||||
Entities.editEntity(entityID, {
|
Entities.editEntity(entityID, {
|
||||||
gravity: data["gravity"],
|
gravity: data["gravity"],
|
||||||
ignoreForCollisions: data["ignoreForCollisions"]
|
ignoreForCollisions: data["ignoreForCollisions"],
|
||||||
|
collisionsWillMove: data["collisionsWillMove"]
|
||||||
});
|
});
|
||||||
data = null;
|
data = null;
|
||||||
}
|
}
|
||||||
|
|
137
examples/grabInspector.js
Normal file
137
examples/grabInspector.js
Normal file
|
@ -0,0 +1,137 @@
|
||||||
|
//
|
||||||
|
// grabInspector.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Seth Alves on 2015-9-30.
|
||||||
|
// Copyright 2015 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("libraries/utils.js");
|
||||||
|
|
||||||
|
var INSPECT_RADIUS = 10;
|
||||||
|
var overlays = {};
|
||||||
|
|
||||||
|
var toType = function(obj) {
|
||||||
|
return ({}).toString.call(obj).match(/\s([a-zA-Z]+)/)[1].toLowerCase()
|
||||||
|
}
|
||||||
|
|
||||||
|
function grabDataToString(grabData) {
|
||||||
|
var result = "";
|
||||||
|
|
||||||
|
for (var argumentName in grabData) {
|
||||||
|
if (grabData.hasOwnProperty(argumentName)) {
|
||||||
|
if (argumentName == "type") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
var arg = grabData[argumentName];
|
||||||
|
var argType = toType(arg);
|
||||||
|
var argString = arg;
|
||||||
|
if (argType == "object") {
|
||||||
|
if (Object.keys(arg).length == 3) {
|
||||||
|
argString = vec3toStr(arg, 1);
|
||||||
|
}
|
||||||
|
} else if (argType == "number") {
|
||||||
|
argString = arg.toFixed(2);
|
||||||
|
}
|
||||||
|
result += argumentName + ": "
|
||||||
|
// + toType(arg) + " -- "
|
||||||
|
+ argString + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function updateOverlay(entityID, grabText) {
|
||||||
|
var properties = Entities.getEntityProperties(entityID, ["position", "dimensions"]);
|
||||||
|
var position = Vec3.sum(properties.position, {x:0, y:properties.dimensions.y, z:0});
|
||||||
|
if (entityID in overlays) {
|
||||||
|
var overlay = overlays[entityID];
|
||||||
|
Overlays.editOverlay(overlay, {
|
||||||
|
text: grabText,
|
||||||
|
position: position
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var lines = grabText.split(/\r\n|\r|\n/);
|
||||||
|
|
||||||
|
var maxLineLength = lines[0].length;
|
||||||
|
for (var i = 1; i < lines.length; i++) {
|
||||||
|
if (lines[i].length > maxLineLength) {
|
||||||
|
maxLineLength = lines[i].length;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var textWidth = maxLineLength * 0.034; // XXX how to know this?
|
||||||
|
var textHeight = .5;
|
||||||
|
var numberOfLines = lines.length;
|
||||||
|
var textMargin = 0.05;
|
||||||
|
var lineHeight = (textHeight - (2 * textMargin)) / numberOfLines;
|
||||||
|
|
||||||
|
overlays[entityID] = Overlays.addOverlay("text3d", {
|
||||||
|
position: position,
|
||||||
|
dimensions: { x: textWidth, y: textHeight },
|
||||||
|
backgroundColor: { red: 0, green: 0, blue: 0},
|
||||||
|
color: { red: 255, green: 255, blue: 255},
|
||||||
|
topMargin: textMargin,
|
||||||
|
leftMargin: textMargin,
|
||||||
|
bottomMargin: textMargin,
|
||||||
|
rightMargin: textMargin,
|
||||||
|
text: grabText,
|
||||||
|
lineHeight: lineHeight,
|
||||||
|
alpha: 0.9,
|
||||||
|
backgroundAlpha: 0.9,
|
||||||
|
ignoreRayIntersection: true,
|
||||||
|
visible: true,
|
||||||
|
isFacingAvatar: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function cleanup() {
|
||||||
|
for (var entityID in overlays) {
|
||||||
|
Overlays.deleteOverlay(overlays[entityID]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Script.setInterval(function() {
|
||||||
|
var nearbyEntities = Entities.findEntities(MyAvatar.position, INSPECT_RADIUS);
|
||||||
|
for (var entityIndex = 0; entityIndex < nearbyEntities.length; entityIndex++) {
|
||||||
|
var entityID = nearbyEntities[entityIndex];
|
||||||
|
var userData = getEntityUserData(entityID);
|
||||||
|
var grabData = userData["grabKey"]
|
||||||
|
|
||||||
|
// {"grabbableKey":{"invertSolidWhileHeld":true},
|
||||||
|
// "grabKey":{"activated":true,"avatarId":"{6ea8b092-10e0-4058-888b-6facc40d0fe9}","refCount":1,"gravity":{"x":0,"y":0,"z":0},"ignoreForCollisions":0,"collisionsWillMove":1}
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (typeof grabData != 'undefined') {
|
||||||
|
var grabText = grabDataToString(grabData);
|
||||||
|
updateOverlay(entityID, grabText);
|
||||||
|
} else {
|
||||||
|
if (entityID in overlays) {
|
||||||
|
Overlays.deleteOverlay(overlays[entityID]);
|
||||||
|
delete overlays[entityID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if an entity is too far away, remove its overlay
|
||||||
|
for (var entityID in overlays) {
|
||||||
|
var position = Entities.getEntityProperties(entityID, ["position"]).position;
|
||||||
|
if (Vec3.distance(position, MyAvatar.position) > INSPECT_RADIUS) {
|
||||||
|
Overlays.deleteOverlay(overlays[entityID]);
|
||||||
|
delete overlays[entityID];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}, 100);
|
||||||
|
|
||||||
|
|
||||||
|
Script.scriptEnding.connect(cleanup);
|
|
@ -62,10 +62,24 @@ var overlaysCounter = new CounterWidget(panel, "Overlays",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
panel.newCheckbox("Display status",
|
// see libraries/render/src/render/Engine.h
|
||||||
function(value) { Scene.setEngineDisplayItemStatus(value); },
|
var showDisplayStatusFlag = 1;
|
||||||
function() { return Scene.doEngineDisplayItemStatus(); },
|
var showNetworkStatusFlag = 2;
|
||||||
function(value) { return (value); }
|
|
||||||
|
panel.newCheckbox("Display status",
|
||||||
|
function(value) { Scene.setEngineDisplayItemStatus(value ?
|
||||||
|
Scene.doEngineDisplayItemStatus() | showDisplayStatusFlag :
|
||||||
|
Scene.doEngineDisplayItemStatus() & ~showDisplayStatusFlag); },
|
||||||
|
function() { return (Scene.doEngineDisplayItemStatus() & showDisplayStatusFlag) > 0; },
|
||||||
|
function(value) { return (value & showDisplayStatusFlag) > 0; }
|
||||||
|
);
|
||||||
|
|
||||||
|
panel.newCheckbox("Network/Physics status",
|
||||||
|
function(value) { Scene.setEngineDisplayItemStatus(value ?
|
||||||
|
Scene.doEngineDisplayItemStatus() | showNetworkStatusFlag :
|
||||||
|
Scene.doEngineDisplayItemStatus() & ~showNetworkStatusFlag); },
|
||||||
|
function() { return (Scene.doEngineDisplayItemStatus() & showNetworkStatusFlag) > 0; },
|
||||||
|
function(value) { return (value & showNetworkStatusFlag) > 0; }
|
||||||
);
|
);
|
||||||
|
|
||||||
var tickTackPeriod = 500;
|
var tickTackPeriod = 500;
|
||||||
|
|
31
interface/resources/icons/statusIconAtlas.svg
Normal file
31
interface/resources/icons/statusIconAtlas.svg
Normal file
|
@ -0,0 +1,31 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!-- Generator: Adobe Illustrator 19.1.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||||
|
<svg version="1.1" baseProfile="tiny" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
|
x="0px" y="0px" width="1600px" height="100px" viewBox="0 0 1600 100" xml:space="preserve">
|
||||||
|
<path fill="#FFFFFF" d="M92.8,69.3c-0.8-1.5-1.9-2.7-3.1-3.8c4.4-11.4,3.7-24.6-2.6-35.8c-9.2-16.3-28.3-24.4-46.3-20l-3.1,0.7
|
||||||
|
l4.9,8.7l1.7-0.3c13.7-2.7,27.6,3.6,34.5,15.7c4.9,8.7,5.5,18.9,1.9,27.9c-2.1,0.1-4.3,0.6-6.2,1.8c-6.5,3.7-8.8,12-5.1,18.5
|
||||||
|
c3.7,6.5,12,8.8,18.5,5.1C94.2,84.1,96.5,75.8,92.8,69.3z"/>
|
||||||
|
<path fill="#FFFFFF" d="M54.2,82.6l-1.5,0.1c-12.3,0.8-24.2-5.6-30.2-16.3c-3.8-6.6-4.9-14.2-3.7-21.3c2.8,0.4,5.9-0.1,8.6-1.6
|
||||||
|
c6.5-3.7,8.8-12,5.1-18.5s-12-8.8-18.5-5.1C7.7,23.7,5.4,32,9,38.5c0.3,0.6,0.7,1.2,1.2,1.7c-2.6,10.3-1.4,21.5,4.1,31.1
|
||||||
|
c7.5,13.2,21.5,21.2,36.5,21.2c1.8,0,3.5-0.1,5.2-0.3l3.6-0.4L54.2,82.6z"/>
|
||||||
|
<path fill="#FFFFFF" d="M67.2,63.4H33.8c-1,0-2.1-0.5-2.6-1.5c-0.5-0.9-0.5-2.1,0-3L47.8,30c0.5-0.9,1.6-1.5,2.6-1.5
|
||||||
|
s2.1,0.5,2.6,1.5l16.7,28.9c0.5,0.9,0.5,2.1,0,3C69.3,62.9,68.3,63.4,67.2,63.4z M39,57.4h23L50.4,37.5L39,57.4z"/>
|
||||||
|
<polygon fill="#FFFFFF" points="175.4,30.6 149.9,8 123.9,30.7 139,30.7 139.2,59.6 161,59.3 160.8,30.7 "/>
|
||||||
|
<polygon fill="#FFFFFF" points="225.6,39.8 251.1,62.5 277.1,39.8 261.9,39.8 261.7,8.9 240,9.2 240.2,39.8 "/>
|
||||||
|
<path fill="#FFFFFF" d="M174.3,42.8c1.8,3.7,2.8,7.8,2.8,12.1c0,15.2-12.3,27.5-27.5,27.5c-15.2,0-27.5-12.3-27.5-27.5
|
||||||
|
c0-4.4,1-8.5,2.9-12.1h-7.9c-1.4,3.8-2.2,7.8-2.2,12.1c0,19.2,15.6,34.7,34.7,34.7c19.2,0,34.7-15.6,34.7-34.7
|
||||||
|
c0-4.3-0.8-8.3-2.2-12.1H174.3z"/>
|
||||||
|
<path fill="#FFFFFF" d="M278.8,53c0.1,0.7,0.1,1.5,0.1,2.2c0,15.2-12.4,27.6-27.6,27.6c-15.2,0-27.6-12.4-27.6-27.6
|
||||||
|
c0-1.1,0.1-2.1,0.2-3.1c-2.1-2.1-4.1-4.1-6.2-6.2c-0.8,3-1.3,6.1-1.3,9.3c0,19.2,15.6,34.9,34.9,34.9s34.9-15.6,34.9-34.9
|
||||||
|
c0-2.9-0.4-5.8-1.1-8.5L278.8,53z"/>
|
||||||
|
<circle fill="none" stroke="#000000" stroke-width="7" stroke-miterlimit="10" stroke-dasharray="7.7202,7.7202" cx="-174" cy="-5.8" r="14.7"/>
|
||||||
|
<path d="M-174-10.6c2.6,0,4.7,2.1,4.7,4.7s-2.1,4.7-4.7,4.7s-4.7-2.1-4.7-4.7S-176.6-10.6-174-10.6 M-174-17.6
|
||||||
|
c-6.5,0-11.7,5.3-11.7,11.7s5.3,11.7,11.7,11.7s11.7-5.3,11.7-11.7S-167.5-17.6-174-17.6L-174-17.6z"/>
|
||||||
|
<path fill="#FFFFFF" d="M353.3,91.2c-0.3,0-0.7,0-1,0c-1.8-0.2-3.5-0.4-5.3-0.7c-21.3-3.6-35.2-22.8-32-44.2
|
||||||
|
c2.7-18.2,17.7-31.4,36.8-32.5c17.2-0.9,33.8,11.4,38.2,28.5c0.8,3.1,1.1,6.3,1.6,9.5c0,0.3,0,0.7,0,1c-0.2,0.9-0.4,1.8-0.5,2.7
|
||||||
|
c-1.3,16.3-12.9,30.1-28.8,34C359.3,90.4,356.3,90.7,353.3,91.2z M353.7,83.9c8.3,0,16.1-3.4,22.6-9.9c2.2-2.2,2-3.1-0.7-4.5
|
||||||
|
c-3.9-1.9-7.8-3.7-11.7-5.6c-4-2-4.6-8.1-1.1-10.8c2-1.5,2.4-3.7,2.1-5.9c-0.2-1.8-1-3.5-1.2-5.3c-0.6-6-5.2-10.2-11.1-10.1
|
||||||
|
c-5.9,0.1-10.4,4.8-10.6,10.9c-0.1,1.4-0.4,2.8-0.9,4.1c-0.6,1.9,0.1,4.9,1.7,6.3c3.8,3.1,3.1,9-1.4,11.2c-3.6,1.7-7.2,3.4-10.8,5.2
|
||||||
|
c-3.4,1.6-3.6,2.5-0.8,5.1C336.2,80.6,343.8,83.9,353.7,83.9z"/>
|
||||||
|
<polygon fill="#FFFFFF" points="445.3,14.1 484.6,14.1 461.5,38.2 485.6,41.4 422.2,86.9 441.2,53.4 425.6,49.3 "/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 3 KiB |
|
@ -3499,10 +3499,6 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) {
|
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowHulls)) {
|
||||||
renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_HULLS);
|
renderDebugFlags = (RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_HULLS);
|
||||||
}
|
}
|
||||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) {
|
|
||||||
renderDebugFlags =
|
|
||||||
(RenderArgs::DebugFlags) (renderDebugFlags | (int)RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP);
|
|
||||||
}
|
|
||||||
renderArgs->_debugFlags = renderDebugFlags;
|
renderArgs->_debugFlags = renderDebugFlags;
|
||||||
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
|
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
|
||||||
}
|
}
|
||||||
|
@ -3562,6 +3558,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
||||||
renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems();
|
renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems();
|
||||||
|
|
||||||
renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus();
|
renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus();
|
||||||
|
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) {
|
||||||
|
renderContext._drawItemStatus |= render::showNetworkStatusFlag;
|
||||||
|
}
|
||||||
renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect();
|
renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect();
|
||||||
|
|
||||||
renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion);
|
renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion);
|
||||||
|
|
|
@ -212,6 +212,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
auto ownerEntity = _ownerEntity.lock();
|
||||||
if (ownerEntity) {
|
if (ownerEntity) {
|
||||||
ownerEntity->setActionDataDirty(true);
|
ownerEntity->setActionDataDirty(true);
|
||||||
|
ownerEntity->setActionDataNeedsTransmit(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
activateBody();
|
activateBody();
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <ObjectMotionState.h>
|
#include <ObjectMotionState.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
#include "../render-utils/simple_vert.h"
|
#include "../render-utils/simple_vert.h"
|
||||||
#include "../render-utils/simple_frag.h"
|
#include "../render-utils/simple_frag.h"
|
||||||
|
|
||||||
|
@ -63,6 +62,4 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
||||||
} else {
|
} else {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidCubeInstance(batch, getTransformToCenter(), cubeColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,67 +0,0 @@
|
||||||
//
|
|
||||||
// RenderableDebugableEntityItem.cpp
|
|
||||||
// libraries/entities-renderer/src/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 5/1/15.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
|
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
|
|
||||||
#include <glm/gtx/quaternion.hpp>
|
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
|
||||||
#include <DeferredLightingEffect.h>
|
|
||||||
#include <ObjectMotionState.h>
|
|
||||||
|
|
||||||
|
|
||||||
void RenderableDebugableEntityItem::renderBoundingBox(EntityItem* entity, RenderArgs* args,
|
|
||||||
float puffedOut, glm::vec4& color) {
|
|
||||||
Q_ASSERT(args->_batch);
|
|
||||||
gpu::Batch& batch = *args->_batch;
|
|
||||||
|
|
||||||
auto shapeTransform = entity->getTransformToCenter();
|
|
||||||
if (puffedOut != 0.0f) {
|
|
||||||
shapeTransform.postScale(1.0f + puffedOut);
|
|
||||||
}
|
|
||||||
batch.setModelTransform(Transform()); // we want to include the scale as well
|
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, color);
|
|
||||||
}
|
|
||||||
|
|
||||||
void RenderableDebugableEntityItem::render(EntityItem* entity, RenderArgs* args) {
|
|
||||||
if (args->_debugFlags & RenderArgs::RENDER_DEBUG_SIMULATION_OWNERSHIP) {
|
|
||||||
Q_ASSERT(args->_batch);
|
|
||||||
gpu::Batch& batch = *args->_batch;
|
|
||||||
|
|
||||||
batch.setModelTransform(entity->getTransformToCenter()); // we want to include the scale as well
|
|
||||||
|
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
const QUuid& myNodeID = nodeList->getSessionUUID();
|
|
||||||
bool highlightSimulationOwnership = (entity->getSimulatorID() == myNodeID);
|
|
||||||
if (highlightSimulationOwnership) {
|
|
||||||
glm::vec4 greenColor(0.0f, 1.0f, 0.2f, 1.0f);
|
|
||||||
renderBoundingBox(entity, args, 0.08f, greenColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
|
||||||
if (now - entity->getLastEditedFromRemote() < 0.1f * USECS_PER_SECOND) {
|
|
||||||
glm::vec4 redColor(1.0f, 0.0f, 0.0f, 1.0f);
|
|
||||||
renderBoundingBox(entity, args, 0.16f, redColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (now - entity->getLastBroadcast() < 0.2f * USECS_PER_SECOND) {
|
|
||||||
glm::vec4 yellowColor(1.0f, 1.0f, 0.2f, 1.0f);
|
|
||||||
renderBoundingBox(entity, args, 0.24f, yellowColor);
|
|
||||||
}
|
|
||||||
|
|
||||||
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
|
||||||
if (motionState && motionState->isActive()) {
|
|
||||||
glm::vec4 blueColor(0.0f, 0.0f, 1.0f, 1.0f);
|
|
||||||
renderBoundingBox(entity, args, 0.32f, blueColor);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,23 +0,0 @@
|
||||||
//
|
|
||||||
// RenderableDebugableEntityItem.h
|
|
||||||
// libraries/entities-renderer/src/
|
|
||||||
//
|
|
||||||
// Created by Seth Alves on 5/1/15.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
#ifndef hifi_RenderableDebugableEntityItem_h
|
|
||||||
#define hifi_RenderableDebugableEntityItem_h
|
|
||||||
|
|
||||||
#include <EntityItem.h>
|
|
||||||
|
|
||||||
class RenderableDebugableEntityItem {
|
|
||||||
public:
|
|
||||||
static void renderBoundingBox(EntityItem* entity, RenderArgs* args, float puffedOut, glm::vec4& color);
|
|
||||||
static void render(EntityItem* entity, RenderArgs* args);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // hifi_RenderableDebugableEntityItem_h
|
|
|
@ -10,6 +10,7 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
|
#include <ObjectMotionState.h>
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
namespace render {
|
namespace render {
|
||||||
|
@ -40,5 +41,60 @@ namespace render {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status::Getters& statusGetters) {
|
||||||
|
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||||
|
quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote();
|
||||||
|
const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND);
|
||||||
|
float normalizedDelta = delta * WAIT_THRESHOLD_INV;
|
||||||
|
// Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD
|
||||||
|
// Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green)
|
||||||
|
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ?
|
||||||
|
render::Item::Status::Value::GREEN :
|
||||||
|
render::Item::Status::Value::RED),
|
||||||
|
(unsigned char) RenderItemStatusIcon::PACKET_RECEIVED);
|
||||||
|
});
|
||||||
|
|
||||||
|
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||||
|
quint64 delta = usecTimestampNow() - entity->getLastBroadcast();
|
||||||
|
const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND);
|
||||||
|
float normalizedDelta = delta * WAIT_THRESHOLD_INV;
|
||||||
|
// Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD
|
||||||
|
// Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green)
|
||||||
|
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ?
|
||||||
|
render::Item::Status::Value::MAGENTA :
|
||||||
|
render::Item::Status::Value::CYAN),
|
||||||
|
(unsigned char)RenderItemStatusIcon::PACKET_SENT);
|
||||||
|
});
|
||||||
|
|
||||||
|
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||||
|
ObjectMotionState* motionState = static_cast<ObjectMotionState*>(entity->getPhysicsInfo());
|
||||||
|
if (motionState && motionState->isActive()) {
|
||||||
|
return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE,
|
||||||
|
(unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET);
|
||||||
|
}
|
||||||
|
return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE,
|
||||||
|
(unsigned char)RenderItemStatusIcon::ACTIVE_IN_BULLET);
|
||||||
|
});
|
||||||
|
|
||||||
|
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
const QUuid& myNodeID = nodeList->getSessionUUID();
|
||||||
|
bool weOwnSimulation = entity->getSimulationOwner().matchesValidID(myNodeID);
|
||||||
|
|
||||||
|
if (weOwnSimulation) {
|
||||||
|
return render::Item::Status::Value(1.0f, render::Item::Status::Value::BLUE,
|
||||||
|
(unsigned char)RenderItemStatusIcon::SIMULATION_OWNER);
|
||||||
|
}
|
||||||
|
return render::Item::Status::Value(0.0f, render::Item::Status::Value::BLUE,
|
||||||
|
(unsigned char)RenderItemStatusIcon::SIMULATION_OWNER);
|
||||||
|
});
|
||||||
|
|
||||||
|
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
||||||
|
if (entity->hasActions()) {
|
||||||
|
return render::Item::Status::Value(1.0f, render::Item::Status::Value::GREEN,
|
||||||
|
(unsigned char)RenderItemStatusIcon::HAS_ACTIONS);
|
||||||
|
}
|
||||||
|
return render::Item::Status::Value(0.0f, render::Item::Status::Value::GREEN,
|
||||||
|
(unsigned char)RenderItemStatusIcon::HAS_ACTIONS);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -15,13 +15,26 @@
|
||||||
#include <render/Scene.h>
|
#include <render/Scene.h>
|
||||||
#include <EntityItem.h>
|
#include <EntityItem.h>
|
||||||
|
|
||||||
|
// These or the icon "name" used by the render item status value, they correspond to the atlas texture used by the DrawItemStatus
|
||||||
|
// job in the current rendering pipeline defined as of now (11/2015) in render-utils/RenderDeferredTask.cpp.
|
||||||
|
enum class RenderItemStatusIcon {
|
||||||
|
ACTIVE_IN_BULLET = 0,
|
||||||
|
PACKET_SENT = 1,
|
||||||
|
PACKET_RECEIVED = 2,
|
||||||
|
SIMULATION_OWNER = 3,
|
||||||
|
HAS_ACTIONS = 4,
|
||||||
|
NONE = 255
|
||||||
|
};
|
||||||
|
|
||||||
|
void makeEntityItemStatusGetters(EntityItemPointer entity, render::Item::Status::Getters& statusGetters);
|
||||||
|
|
||||||
|
|
||||||
class RenderableEntityItemProxy {
|
class RenderableEntityItemProxy {
|
||||||
public:
|
public:
|
||||||
RenderableEntityItemProxy(EntityItemPointer entity) : entity(entity) { }
|
RenderableEntityItemProxy(EntityItemPointer entity) : entity(entity) { }
|
||||||
typedef render::Payload<RenderableEntityItemProxy> Payload;
|
typedef render::Payload<RenderableEntityItemProxy> Payload;
|
||||||
typedef Payload::DataPointer Pointer;
|
typedef Payload::DataPointer Pointer;
|
||||||
|
|
||||||
EntityItemPointer entity;
|
EntityItemPointer entity;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -36,19 +49,23 @@ class SimpleRenderableEntityItem {
|
||||||
public:
|
public:
|
||||||
bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||||
_myItem = scene->allocateID();
|
_myItem = scene->allocateID();
|
||||||
|
|
||||||
auto renderData = std::make_shared<RenderableEntityItemProxy>(self);
|
auto renderData = std::make_shared<RenderableEntityItemProxy>(self);
|
||||||
auto renderPayload = std::make_shared<RenderableEntityItemProxy::Payload>(renderData);
|
auto renderPayload = std::make_shared<RenderableEntityItemProxy::Payload>(renderData);
|
||||||
|
|
||||||
|
render::Item::Status::Getters statusGetters;
|
||||||
|
makeEntityItemStatusGetters(self, statusGetters);
|
||||||
|
renderPayload->addStatusGetters(statusGetters);
|
||||||
|
|
||||||
pendingChanges.resetItem(_myItem, renderPayload);
|
pendingChanges.resetItem(_myItem, renderPayload);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||||
pendingChanges.removeItem(_myItem);
|
pendingChanges.removeItem(_myItem);
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
render::ItemID _myItem;
|
render::ItemID _myItem;
|
||||||
};
|
};
|
||||||
|
@ -62,5 +79,4 @@ private: \
|
||||||
SimpleRenderableEntityItem _renderHelper;
|
SimpleRenderableEntityItem _renderHelper;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#endif // hifi_RenderableEntityItem_h
|
#endif // hifi_RenderableEntityItem_h
|
||||||
|
|
|
@ -54,6 +54,4 @@ void RenderableLineEntityItem::render(RenderArgs* args) {
|
||||||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
|
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
|
||||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
#define hifi_RenderableLineEntityItem_h
|
#define hifi_RenderableLineEntityItem_h
|
||||||
|
|
||||||
#include <LineEntityItem.h>
|
#include <LineEntityItem.h>
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,9 @@
|
||||||
|
|
||||||
#include "EntityTreeRenderer.h"
|
#include "EntityTreeRenderer.h"
|
||||||
#include "EntitiesRendererLogging.h"
|
#include "EntitiesRendererLogging.h"
|
||||||
|
#include "RenderableEntityItem.h"
|
||||||
#include "RenderableModelEntityItem.h"
|
#include "RenderableModelEntityItem.h"
|
||||||
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||||
return std::make_shared<RenderableModelEntityItem>(entityID, properties);
|
return std::make_shared<RenderableModelEntityItem>(entityID, properties);
|
||||||
|
@ -179,25 +181,6 @@ namespace render {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void makeEntityItemStatusGetters(RenderableModelEntityItem* entity, render::Item::Status::Getters& statusGetters) {
|
|
||||||
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
|
||||||
quint64 delta = usecTimestampNow() - entity->getLastEditedFromRemote();
|
|
||||||
const float WAIT_THRESHOLD_INV = 1.0f / (0.2f * USECS_PER_SECOND);
|
|
||||||
float normalizedDelta = delta * WAIT_THRESHOLD_INV;
|
|
||||||
// Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD
|
|
||||||
// Color is red if last update is after WAIT_THRESHOLD, green otherwise (120 deg is green)
|
|
||||||
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::GREEN : render::Item::Status::Value::RED));
|
|
||||||
});
|
|
||||||
statusGetters.push_back([entity] () -> render::Item::Status::Value {
|
|
||||||
quint64 delta = usecTimestampNow() - entity->getLastBroadcast();
|
|
||||||
const float WAIT_THRESHOLD_INV = 1.0f / (0.4f * USECS_PER_SECOND);
|
|
||||||
float normalizedDelta = delta * WAIT_THRESHOLD_INV;
|
|
||||||
// Status icon will scale from 1.0f down to 0.0f after WAIT_THRESHOLD
|
|
||||||
// Color is Magenta if last update is after WAIT_THRESHOLD, cyan otherwise (180 deg is green)
|
|
||||||
return render::Item::Status::Value(1.0f - normalizedDelta, (normalizedDelta > 1.0f ? render::Item::Status::Value::MAGENTA : render::Item::Status::Value::CYAN));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene,
|
||||||
render::PendingChanges& pendingChanges) {
|
render::PendingChanges& pendingChanges) {
|
||||||
_myMetaItem = scene->allocateID();
|
_myMetaItem = scene->allocateID();
|
||||||
|
@ -209,11 +192,11 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
|
||||||
|
|
||||||
if (_model) {
|
if (_model) {
|
||||||
render::Item::Status::Getters statusGetters;
|
render::Item::Status::Getters statusGetters;
|
||||||
makeEntityItemStatusGetters(this, statusGetters);
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
|
|
||||||
// note: we don't care if the model fails to add items, we always added our meta item and therefore we return
|
// note: we don't care if the model fails to add items, we always added our meta item and therefore we return
|
||||||
// true so that the system knows our meta item is in the scene!
|
// true so that the system knows our meta item is in the scene!
|
||||||
_model->addToScene(scene, pendingChanges, statusGetters);
|
_model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -245,14 +228,16 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
|
|
||||||
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
// check to see if when we added our models to the scene they were ready, if they were not ready, then
|
||||||
// fix them up in the scene
|
// fix them up in the scene
|
||||||
if (_model->needsFixupInScene()) {
|
bool shouldShowCollisionHull = (args->_debugFlags & (int)RenderArgs::RENDER_DEBUG_HULLS) > 0;
|
||||||
|
if (_model->needsFixupInScene() || _showCollisionHull != shouldShowCollisionHull) {
|
||||||
|
_showCollisionHull = shouldShowCollisionHull;
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
|
|
||||||
_model->removeFromScene(scene, pendingChanges);
|
_model->removeFromScene(scene, pendingChanges);
|
||||||
|
|
||||||
render::Item::Status::Getters statusGetters;
|
render::Item::Status::Getters statusGetters;
|
||||||
makeEntityItemStatusGetters(this, statusGetters);
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
_model->addToScene(scene, pendingChanges, statusGetters);
|
_model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull);
|
||||||
|
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
}
|
}
|
||||||
|
@ -274,7 +259,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
|
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
|
||||||
getModel(renderer);
|
getModel(renderer);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_model) {
|
if (_model) {
|
||||||
// handle animations..
|
// handle animations..
|
||||||
if (hasAnimation()) {
|
if (hasAnimation()) {
|
||||||
|
@ -320,11 +305,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||||
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
gpu::Batch& batch = *args->_batch;
|
||||||
|
auto shapeTransform = getTransformToCenter();
|
||||||
|
batch.setModelTransform(Transform()); // we want to include the scale as well
|
||||||
|
DependencyManager::get<DeferredLightingEffect>()->renderWireCubeInstance(batch, shapeTransform, greenColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
||||||
|
|
|
@ -16,7 +16,6 @@
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
#include <ModelEntityItem.h>
|
#include <ModelEntityItem.h>
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
class EntityTreeRenderer;
|
class EntityTreeRenderer;
|
||||||
|
@ -82,6 +81,8 @@ private:
|
||||||
bool _dimensionsInitialized = true;
|
bool _dimensionsInitialized = true;
|
||||||
|
|
||||||
render::ItemID _myMetaItem;
|
render::ItemID _myMetaItem;
|
||||||
|
|
||||||
|
bool _showCollisionHull = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_RenderableModelEntityItem_h
|
#endif // hifi_RenderableModelEntityItem_h
|
||||||
|
|
|
@ -139,6 +139,9 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self,
|
||||||
_renderItemId = scene->allocateID();
|
_renderItemId = scene->allocateID();
|
||||||
auto renderData = ParticlePayload::Pointer(particlePayload);
|
auto renderData = ParticlePayload::Pointer(particlePayload);
|
||||||
auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData));
|
auto renderPayload = render::PayloadPointer(new ParticlePayload::Payload(renderData));
|
||||||
|
render::Item::Status::Getters statusGetters;
|
||||||
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
|
renderPayload->addStatusGetters(statusGetters);
|
||||||
pendingChanges.resetItem(_renderItemId, renderPayload);
|
pendingChanges.resetItem(_renderItemId, renderPayload);
|
||||||
_scene = scene;
|
_scene = scene;
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -153,6 +153,4 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
||||||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||||
|
|
||||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
|
|
||||||
#include <gpu/Batch.h>
|
#include <gpu/Batch.h>
|
||||||
#include <PolyLineEntityItem.h>
|
#include <PolyLineEntityItem.h>
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <QReadWriteLock>
|
#include <QReadWriteLock>
|
||||||
|
|
|
@ -538,8 +538,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
||||||
batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z);
|
batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z);
|
||||||
|
|
||||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
||||||
|
@ -551,6 +549,10 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
||||||
auto renderData = PolyVoxPayload::Pointer(renderItem);
|
auto renderData = PolyVoxPayload::Pointer(renderItem);
|
||||||
auto renderPayload = std::make_shared<PolyVoxPayload::Payload>(renderData);
|
auto renderPayload = std::make_shared<PolyVoxPayload::Payload>(renderData);
|
||||||
|
|
||||||
|
render::Item::Status::Getters statusGetters;
|
||||||
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
|
renderPayload->addStatusGetters(statusGetters);
|
||||||
|
|
||||||
pendingChanges.resetItem(_myItem, renderPayload);
|
pendingChanges.resetItem(_myItem, renderPayload);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -21,7 +21,6 @@
|
||||||
#include <TextureCache.h>
|
#include <TextureCache.h>
|
||||||
|
|
||||||
#include "PolyVoxEntityItem.h"
|
#include "PolyVoxEntityItem.h"
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
#include "RenderableEntityItem.h"
|
#include "RenderableEntityItem.h"
|
||||||
#include "gpu/Context.h"
|
#include "gpu/Context.h"
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
|
||||||
#include "RenderableDebugableEntityItem.h"
|
|
||||||
#include "../render-utils/simple_vert.h"
|
#include "../render-utils/simple_vert.h"
|
||||||
#include "../render-utils/simple_frag.h"
|
#include "../render-utils/simple_frag.h"
|
||||||
|
|
||||||
|
@ -70,7 +69,4 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
|
||||||
batch.setModelTransform(Transform());
|
batch.setModelTransform(Transform());
|
||||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
|
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
RenderableDebugableEntityItem::render(this, args);
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -19,6 +19,8 @@
|
||||||
#include <GeometryCache.h>
|
#include <GeometryCache.h>
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
|
||||||
|
#include "RenderableEntityItem.h"
|
||||||
|
|
||||||
// Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
// Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
||||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||||
|
@ -112,7 +114,9 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
|
||||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||||
render::PendingChanges pendingChanges;
|
render::PendingChanges pendingChanges;
|
||||||
_model->removeFromScene(scene, pendingChanges);
|
_model->removeFromScene(scene, pendingChanges);
|
||||||
_model->addToScene(scene, pendingChanges);
|
render::Item::Status::Getters statusGetters;
|
||||||
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
|
_model->addToScene(scene, pendingChanges, false);
|
||||||
|
|
||||||
scene->enqueuePendingChanges(pendingChanges);
|
scene->enqueuePendingChanges(pendingChanges);
|
||||||
|
|
||||||
|
@ -203,7 +207,11 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt
|
||||||
|
|
||||||
auto renderData = std::make_shared<RenderableZoneEntityItemMeta>(self);
|
auto renderData = std::make_shared<RenderableZoneEntityItemMeta>(self);
|
||||||
auto renderPayload = std::make_shared<RenderableZoneEntityItemMeta::Payload>(renderData);
|
auto renderPayload = std::make_shared<RenderableZoneEntityItemMeta::Payload>(renderData);
|
||||||
|
|
||||||
|
render::Item::Status::Getters statusGetters;
|
||||||
|
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||||
|
renderPayload->addStatusGetters(statusGetters);
|
||||||
|
|
||||||
pendingChanges.resetItem(_myMetaItem, renderPayload);
|
pendingChanges.resetItem(_myMetaItem, renderPayload);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,3 +304,24 @@ QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType)
|
||||||
entityActionType = (EntityActionType)actionTypeAsInt;
|
entityActionType = (EntityActionType)actionTypeAsInt;
|
||||||
return stream;
|
return stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QString serializedActionsToDebugString(QByteArray data) {
|
||||||
|
if (data.size() == 0) {
|
||||||
|
return QString();
|
||||||
|
}
|
||||||
|
QVector<QByteArray> serializedActions;
|
||||||
|
QDataStream serializedActionsStream(data);
|
||||||
|
serializedActionsStream >> serializedActions;
|
||||||
|
|
||||||
|
QString result;
|
||||||
|
foreach(QByteArray serializedAction, serializedActions) {
|
||||||
|
QDataStream serializedActionStream(serializedAction);
|
||||||
|
EntityActionType actionType;
|
||||||
|
QUuid actionID;
|
||||||
|
serializedActionStream >> actionType;
|
||||||
|
serializedActionStream >> actionID;
|
||||||
|
result += EntityActionInterface::actionTypeToString(actionType) + "-" + actionID.toString() + " ";
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
|
@ -89,4 +89,6 @@ typedef std::shared_ptr<EntityActionInterface> EntityActionPointer;
|
||||||
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType);
|
QDataStream& operator<<(QDataStream& stream, const EntityActionType& entityActionType);
|
||||||
QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType);
|
QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType);
|
||||||
|
|
||||||
|
QString serializedActionsToDebugString(QByteArray data);
|
||||||
|
|
||||||
#endif // hifi_EntityActionInterface_h
|
#endif // hifi_EntityActionInterface_h
|
||||||
|
|
|
@ -630,6 +630,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
dataAt += bytes;
|
dataAt += bytes;
|
||||||
bytesRead += bytes;
|
bytesRead += bytes;
|
||||||
|
|
||||||
|
if (wantTerseEditLogging() && _simulationOwner != newSimOwner) {
|
||||||
|
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner;
|
||||||
|
}
|
||||||
if (_simulationOwner.set(newSimOwner)) {
|
if (_simulationOwner.set(newSimOwner)) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
||||||
}
|
}
|
||||||
|
@ -704,17 +707,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
READ_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, QString, setCollisionSoundURL);
|
||||||
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
|
READ_ENTITY_PROPERTY(PROP_HREF, QString, setHref);
|
||||||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||||
|
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
||||||
{ // When we own the simulation we don't accept updates to the entity's actions
|
|
||||||
// but since we're using macros below we have to temporarily modify overwriteLocalData.
|
|
||||||
// NOTE: this prevents userB from adding an action to an object1 when UserA
|
|
||||||
// has simulation ownership of it.
|
|
||||||
// TODO: figure out how to allow multiple users to update actions simultaneously
|
|
||||||
bool oldOverwrite = overwriteLocalData;
|
|
||||||
overwriteLocalData = overwriteLocalData && !weOwnSimulation;
|
|
||||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
|
||||||
overwriteLocalData = oldOverwrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||||
propertyFlags, overwriteLocalData, somethingChanged);
|
propertyFlags, overwriteLocalData, somethingChanged);
|
||||||
|
@ -737,7 +730,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
// this "new" data is actually slightly out of date. We calculate the time we need to skip forward and
|
||||||
// use our simulation helper routine to get a best estimate of where the entity should be.
|
// use our simulation helper routine to get a best estimate of where the entity should be.
|
||||||
float skipTimeForward = (float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND);
|
float skipTimeForward = (float)(now - lastSimulatedFromBufferAdjusted) / (float)(USECS_PER_SECOND);
|
||||||
|
|
||||||
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
||||||
// we don't want the side effect of flag setting.
|
// we don't want the side effect of flag setting.
|
||||||
simulateKinematicMotion(skipTimeForward, false);
|
simulateKinematicMotion(skipTimeForward, false);
|
||||||
|
@ -745,7 +738,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
||||||
|
|
||||||
if (overwriteLocalData) {
|
if (overwriteLocalData) {
|
||||||
if (!_simulationOwner.matchesValidID(myNodeID)) {
|
if (!_simulationOwner.matchesValidID(myNodeID)) {
|
||||||
|
|
||||||
_lastSimulated = now;
|
_lastSimulated = now;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -996,6 +988,11 @@ EntityTreePointer EntityItem::getTree() const {
|
||||||
return tree;
|
return tree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool EntityItem::wantTerseEditLogging() {
|
||||||
|
EntityTreePointer tree = getTree();
|
||||||
|
return tree ? tree->wantTerseEditLogging() : false;
|
||||||
|
}
|
||||||
|
|
||||||
glm::mat4 EntityItem::getEntityToWorldMatrix() const {
|
glm::mat4 EntityItem::getEntityToWorldMatrix() const {
|
||||||
glm::mat4 translation = glm::translate(getPosition());
|
glm::mat4 translation = glm::translate(getPosition());
|
||||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||||
|
@ -1492,20 +1489,35 @@ void EntityItem::updateCreated(uint64_t value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) {
|
void EntityItem::setSimulationOwner(const QUuid& id, quint8 priority) {
|
||||||
|
if (wantTerseEditLogging() && (id != _simulationOwner.getID() || priority != _simulationOwner.getPriority())) {
|
||||||
|
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority;
|
||||||
|
}
|
||||||
_simulationOwner.set(id, priority);
|
_simulationOwner.set(id, priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::setSimulationOwner(const SimulationOwner& owner) {
|
void EntityItem::setSimulationOwner(const SimulationOwner& owner) {
|
||||||
|
if (wantTerseEditLogging() && _simulationOwner != owner) {
|
||||||
|
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner;
|
||||||
|
}
|
||||||
|
|
||||||
_simulationOwner.set(owner);
|
_simulationOwner.set(owner);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::updateSimulatorID(const QUuid& value) {
|
void EntityItem::updateSimulatorID(const QUuid& value) {
|
||||||
|
if (wantTerseEditLogging() && _simulationOwner.getID() != value) {
|
||||||
|
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value;
|
||||||
|
}
|
||||||
|
|
||||||
if (_simulationOwner.setID(value)) {
|
if (_simulationOwner.setID(value)) {
|
||||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityItem::clearSimulationOwnership() {
|
void EntityItem::clearSimulationOwnership() {
|
||||||
|
if (wantTerseEditLogging() && !_simulationOwner.isNull()) {
|
||||||
|
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null";
|
||||||
|
}
|
||||||
|
|
||||||
_simulationOwner.clear();
|
_simulationOwner.clear();
|
||||||
// don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership()
|
// don't bother setting the DIRTY_SIMULATOR_ID flag because clearSimulationOwnership()
|
||||||
// is only ever called entity-server-side and the flags are only used client-side
|
// is only ever called entity-server-side and the flags are only used client-side
|
||||||
|
@ -1607,6 +1619,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s
|
||||||
bool success = true;
|
bool success = true;
|
||||||
serializeActions(success, _allActionsDataCache);
|
serializeActions(success, _allActionsDataCache);
|
||||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||||
|
setActionDataNeedsTransmit(true);
|
||||||
return success;
|
return success;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1649,7 +1662,7 @@ void EntityItem::deserializeActionsInternal() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
|
EntityTreePointer entityTree = getTree();
|
||||||
assert(entityTree);
|
assert(entityTree);
|
||||||
EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||||
assert(simulation);
|
assert(simulation);
|
||||||
|
@ -1770,6 +1783,7 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const {
|
||||||
serializedActionsStream << serializedActions;
|
serializedActionsStream << serializedActions;
|
||||||
|
|
||||||
if (result.size() >= _maxActionsDataSize) {
|
if (result.size() >= _maxActionsDataSize) {
|
||||||
|
qDebug() << "EntityItem::serializeActions size is too large -- " << result.size() << ">=" << _maxActionsDataSize;
|
||||||
success = false;
|
success = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -307,6 +307,7 @@ public:
|
||||||
|
|
||||||
QString getName() const { return _name; }
|
QString getName() const { return _name; }
|
||||||
void setName(const QString& value) { _name = value; }
|
void setName(const QString& value) { _name = value; }
|
||||||
|
QString getDebugName() { return _name != "" ? _name : getID().toString(); }
|
||||||
|
|
||||||
bool getVisible() const { return _visible; }
|
bool getVisible() const { return _visible; }
|
||||||
void setVisible(bool value) { _visible = value; }
|
void setVisible(bool value) { _visible = value; }
|
||||||
|
@ -381,6 +382,7 @@ public:
|
||||||
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
||||||
EntityTreeElementPointer getElement() const { return _element; }
|
EntityTreeElementPointer getElement() const { return _element; }
|
||||||
EntityTreePointer getTree() const;
|
EntityTreePointer getTree() const;
|
||||||
|
bool wantTerseEditLogging();
|
||||||
|
|
||||||
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
|
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
|
||||||
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
|
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
|
||||||
|
@ -406,7 +408,13 @@ public:
|
||||||
QList<QUuid> getActionIDs() { return _objectActions.keys(); }
|
QList<QUuid> getActionIDs() { return _objectActions.keys(); }
|
||||||
QVariantMap getActionArguments(const QUuid& actionID) const;
|
QVariantMap getActionArguments(const QUuid& actionID) const;
|
||||||
void deserializeActions();
|
void deserializeActions();
|
||||||
|
|
||||||
void setActionDataDirty(bool value) const { _actionDataDirty = value; }
|
void setActionDataDirty(bool value) const { _actionDataDirty = value; }
|
||||||
|
bool actionDataDirty() const { return _actionDataDirty; }
|
||||||
|
|
||||||
|
void setActionDataNeedsTransmit(bool value) const { _actionDataNeedsTransmit = value; }
|
||||||
|
bool actionDataNeedsTransmit() const { return _actionDataNeedsTransmit; }
|
||||||
|
|
||||||
bool shouldSuppressLocationEdits() const;
|
bool shouldSuppressLocationEdits() const;
|
||||||
|
|
||||||
void setSourceUUID(const QUuid& sourceUUID) { _sourceUUID = sourceUUID; }
|
void setSourceUUID(const QUuid& sourceUUID) { _sourceUUID = sourceUUID; }
|
||||||
|
@ -439,7 +447,7 @@ protected:
|
||||||
mutable bool _recalcAABox = true;
|
mutable bool _recalcAABox = true;
|
||||||
mutable bool _recalcMinAACube = true;
|
mutable bool _recalcMinAACube = true;
|
||||||
mutable bool _recalcMaxAACube = true;
|
mutable bool _recalcMaxAACube = true;
|
||||||
|
|
||||||
float _glowLevel;
|
float _glowLevel;
|
||||||
float _localRenderAlpha;
|
float _localRenderAlpha;
|
||||||
float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3
|
float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3
|
||||||
|
@ -510,6 +518,7 @@ protected:
|
||||||
void checkWaitingToRemove(EntitySimulation* simulation = nullptr);
|
void checkWaitingToRemove(EntitySimulation* simulation = nullptr);
|
||||||
mutable QSet<QUuid> _actionsToRemove;
|
mutable QSet<QUuid> _actionsToRemove;
|
||||||
mutable bool _actionDataDirty = false;
|
mutable bool _actionDataDirty = false;
|
||||||
|
mutable bool _actionDataNeedsTransmit = false;
|
||||||
// _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag
|
// _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag
|
||||||
static quint64 _rememberDeletedActionTime;
|
static quint64 _rememberDeletedActionTime;
|
||||||
mutable QHash<QUuid, quint64> _previouslyDeletedActions;
|
mutable QHash<QUuid, quint64> _previouslyDeletedActions;
|
||||||
|
|
|
@ -611,7 +611,8 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
||||||
const QVariantMap& arguments) {
|
const QVariantMap& arguments) {
|
||||||
QUuid actionID = QUuid::createUuid();
|
QUuid actionID = QUuid::createUuid();
|
||||||
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
auto actionFactory = DependencyManager::get<EntityActionFactoryInterface>();
|
||||||
bool success = actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
|
bool success = false;
|
||||||
|
actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
|
||||||
// create this action even if the entity doesn't have physics info. it will often be the
|
// create this action even if the entity doesn't have physics info. it will often be the
|
||||||
// case that a script adds an action immediately after an object is created, and the physicsInfo
|
// case that a script adds an action immediately after an object is created, and the physicsInfo
|
||||||
// is computed asynchronously.
|
// is computed asynchronously.
|
||||||
|
@ -623,16 +624,16 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments);
|
EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments);
|
||||||
if (action) {
|
if (!action) {
|
||||||
entity->addAction(simulation, action);
|
return false;
|
||||||
auto nodeList = DependencyManager::get<NodeList>();
|
|
||||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
|
||||||
if (entity->getSimulatorID() != myNodeID) {
|
|
||||||
entity->flagForOwnership();
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
success = entity->addAction(simulation, action);
|
||||||
|
auto nodeList = DependencyManager::get<NodeList>();
|
||||||
|
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||||
|
if (entity->getSimulatorID() != myNodeID) {
|
||||||
|
entity->flagForOwnership();
|
||||||
|
}
|
||||||
|
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||||
});
|
});
|
||||||
if (success) {
|
if (success) {
|
||||||
return actionID;
|
return actionID;
|
||||||
|
@ -656,9 +657,12 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) {
|
bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) {
|
||||||
return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
|
bool success = false;
|
||||||
return entity->removeAction(simulation, actionID);
|
actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
|
||||||
|
success = entity->removeAction(simulation, actionID);
|
||||||
|
return false; // Physics will cause a packet to be sent, so don't send from here.
|
||||||
});
|
});
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
QVector<QUuid> EntityScriptingInterface::getActionIDs(const QUuid& entityID) {
|
QVector<QUuid> EntityScriptingInterface::getActionIDs(const QUuid& entityID) {
|
||||||
|
|
|
@ -198,6 +198,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
||||||
properties.setVelocityChanged(false);
|
properties.setVelocityChanged(false);
|
||||||
properties.setAngularVelocityChanged(false);
|
properties.setAngularVelocityChanged(false);
|
||||||
properties.setAccelerationChanged(false);
|
properties.setAccelerationChanged(false);
|
||||||
|
|
||||||
|
if (wantTerseEditLogging()) {
|
||||||
|
qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else client accepts what the server says
|
// else client accepts what the server says
|
||||||
|
@ -612,6 +616,14 @@ EntityItemPointer EntityTree::findEntityByEntityItemID(const EntityItemID& entit
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<QString>& changedProperties) {
|
void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<QString>& changedProperties) {
|
||||||
|
static quint64 lastTerseLog = 0;
|
||||||
|
quint64 now = usecTimestampNow();
|
||||||
|
|
||||||
|
if (now - lastTerseLog > USECS_PER_SECOND) {
|
||||||
|
qCDebug(entities) << "-------------------------";
|
||||||
|
}
|
||||||
|
lastTerseLog = now;
|
||||||
|
|
||||||
if (properties.simulationOwnerChanged()) {
|
if (properties.simulationOwnerChanged()) {
|
||||||
int simIndex = changedProperties.indexOf("simulationOwner");
|
int simIndex = changedProperties.indexOf("simulationOwner");
|
||||||
if (simIndex >= 0) {
|
if (simIndex >= 0) {
|
||||||
|
@ -619,6 +631,79 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
||||||
changedProperties[simIndex] = QString("simulationOwner:") + QString::number((int)simOwner.getPriority());
|
changedProperties[simIndex] = QString("simulationOwner:") + QString::number((int)simOwner.getPriority());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (properties.velocityChanged()) {
|
||||||
|
int index = changedProperties.indexOf("velocity");
|
||||||
|
if (index >= 0) {
|
||||||
|
glm::vec3 value = properties.getVelocity();
|
||||||
|
QString changeHint = "0";
|
||||||
|
if (value.x + value.y + value.z > 0) {
|
||||||
|
changeHint = "+";
|
||||||
|
} else if (value.x + value.y + value.z < 0) {
|
||||||
|
changeHint = "-";
|
||||||
|
}
|
||||||
|
changedProperties[index] = QString("velocity:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.gravityChanged()) {
|
||||||
|
int index = changedProperties.indexOf("gravity");
|
||||||
|
if (index >= 0) {
|
||||||
|
glm::vec3 value = properties.getGravity();
|
||||||
|
QString changeHint = "0";
|
||||||
|
if (value.x + value.y + value.z > 0) {
|
||||||
|
changeHint = "+";
|
||||||
|
} else if (value.x + value.y + value.z < 0) {
|
||||||
|
changeHint = "-";
|
||||||
|
}
|
||||||
|
changedProperties[index] = QString("gravity:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.actionDataChanged()) {
|
||||||
|
int index = changedProperties.indexOf("actionData");
|
||||||
|
if (index >= 0) {
|
||||||
|
QByteArray value = properties.getActionData();
|
||||||
|
QString changeHint = serializedActionsToDebugString(value);
|
||||||
|
changedProperties[index] = QString("actionData:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.ignoreForCollisionsChanged()) {
|
||||||
|
int index = changedProperties.indexOf("ignoreForCollisions");
|
||||||
|
if (index >= 0) {
|
||||||
|
bool value = properties.getIgnoreForCollisions();
|
||||||
|
QString changeHint = "0";
|
||||||
|
if (value) {
|
||||||
|
changeHint = "1";
|
||||||
|
}
|
||||||
|
changedProperties[index] = QString("ignoreForCollisions:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.collisionsWillMoveChanged()) {
|
||||||
|
int index = changedProperties.indexOf("collisionsWillMove");
|
||||||
|
if (index >= 0) {
|
||||||
|
bool value = properties.getCollisionsWillMove();
|
||||||
|
QString changeHint = "0";
|
||||||
|
if (value) {
|
||||||
|
changeHint = "1";
|
||||||
|
}
|
||||||
|
changedProperties[index] = QString("collisionsWillMove:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (properties.lockedChanged()) {
|
||||||
|
int index = changedProperties.indexOf("locked");
|
||||||
|
if (index >= 0) {
|
||||||
|
bool value = properties.getLocked();
|
||||||
|
QString changeHint = "0";
|
||||||
|
if (value) {
|
||||||
|
changeHint = "1";
|
||||||
|
}
|
||||||
|
changedProperties[index] = QString("locked:") + changeHint;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
|
int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* editData, int maxLength,
|
||||||
|
@ -673,7 +758,8 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi
|
||||||
if (wantTerseEditLogging()) {
|
if (wantTerseEditLogging()) {
|
||||||
QList<QString> changedProperties = properties.listChangedProperties();
|
QList<QString> changedProperties = properties.listChangedProperties();
|
||||||
fixupTerseEditLogging(properties, changedProperties);
|
fixupTerseEditLogging(properties, changedProperties);
|
||||||
qCDebug(entities) << "edit" << entityItemID.toString() << changedProperties;
|
qCDebug(entities) << senderNode->getUUID() << "edit" <<
|
||||||
|
existingEntity->getDebugName() << changedProperties;
|
||||||
}
|
}
|
||||||
endLogging = usecTimestampNow();
|
endLogging = usecTimestampNow();
|
||||||
|
|
||||||
|
@ -703,7 +789,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi
|
||||||
if (wantTerseEditLogging()) {
|
if (wantTerseEditLogging()) {
|
||||||
QList<QString> changedProperties = properties.listChangedProperties();
|
QList<QString> changedProperties = properties.listChangedProperties();
|
||||||
fixupTerseEditLogging(properties, changedProperties);
|
fixupTerseEditLogging(properties, changedProperties);
|
||||||
qCDebug(entities) << "add" << entityItemID.toString() << changedProperties;
|
qCDebug(entities) << senderNode->getUUID() << "add" << entityItemID << changedProperties;
|
||||||
}
|
}
|
||||||
endLogging = usecTimestampNow();
|
endLogging = usecTimestampNow();
|
||||||
|
|
||||||
|
|
|
@ -157,7 +157,7 @@ void SimulationOwner::test() {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool SimulationOwner::operator!=(const SimulationOwner& other) {
|
bool SimulationOwner::operator!=(const SimulationOwner& other) {
|
||||||
return (_id != other._id && _priority != other._priority);
|
return (_id != other._id || _priority != other._priority);
|
||||||
}
|
}
|
||||||
|
|
||||||
SimulationOwner& SimulationOwner::operator=(const SimulationOwner& other) {
|
SimulationOwner& SimulationOwner::operator=(const SimulationOwner& other) {
|
||||||
|
|
|
@ -331,7 +331,7 @@ public:
|
||||||
|
|
||||||
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0), _stride); }
|
template <typename T> Iterator<T> begin() { return Iterator<T>(&edit<T>(0), _stride); }
|
||||||
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
template <typename T> Iterator<T> end() { return Iterator<T>(&edit<T>(getNum<T>()), _stride); }
|
||||||
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(0), _stride); }
|
template <typename T> Iterator<const T> cbegin() const { return Iterator<const T>(&get<T>(), _stride); }
|
||||||
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>()), _stride); }
|
template <typename T> Iterator<const T> cend() const { return Iterator<const T>(&get<T>(getNum<T>()), _stride); }
|
||||||
|
|
||||||
// the number of elements of the specified type fitting in the view size
|
// the number of elements of the specified type fitting in the view size
|
||||||
|
|
|
@ -112,8 +112,8 @@ bool EntityMotionState::handleEasyChanges(uint32_t flags, PhysicsEngine* engine)
|
||||||
_outgoingPriority = NO_PRORITY;
|
_outgoingPriority = NO_PRORITY;
|
||||||
} else {
|
} else {
|
||||||
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||||
if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() > _outgoingPriority) {
|
if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) {
|
||||||
// we own the simulation or our priority looses to remote
|
// we own the simulation or our priority looses to (or ties with) remote
|
||||||
_outgoingPriority = NO_PRORITY;
|
_outgoingPriority = NO_PRORITY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -244,7 +244,7 @@ bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
assert(entityTreeIsLocked());
|
assert(entityTreeIsLocked());
|
||||||
return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID();
|
return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID() || _entity->actionDataNeedsTransmit();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
|
@ -292,7 +292,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||||
_serverPosition += dt * _serverVelocity;
|
_serverPosition += dt * _serverVelocity;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_serverActionData != _entity->getActionData()) {
|
if (_entity->actionDataNeedsTransmit()) {
|
||||||
setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY);
|
setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -370,11 +370,15 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
||||||
assert(_body);
|
assert(_body);
|
||||||
assert(entityTreeIsLocked());
|
assert(entityTreeIsLocked());
|
||||||
|
|
||||||
|
if (_entity->actionDataNeedsTransmit()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_entity->getSimulatorID() != sessionID) {
|
if (_entity->getSimulatorID() != sessionID) {
|
||||||
// we don't own the simulation, but maybe we should...
|
// we don't own the simulation, but maybe we should...
|
||||||
if (_outgoingPriority != NO_PRORITY) {
|
if (_outgoingPriority != NO_PRORITY) {
|
||||||
if (_outgoingPriority < _entity->getSimulationPriority()) {
|
if (_outgoingPriority < _entity->getSimulationPriority()) {
|
||||||
// our priority looses to remote, so we don't bother to bid
|
// our priority loses to remote, so we don't bother to bid
|
||||||
_outgoingPriority = NO_PRORITY;
|
_outgoingPriority = NO_PRORITY;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -456,7 +460,10 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
||||||
properties.setVelocity(_serverVelocity);
|
properties.setVelocity(_serverVelocity);
|
||||||
properties.setAcceleration(_serverAcceleration);
|
properties.setAcceleration(_serverAcceleration);
|
||||||
properties.setAngularVelocity(_serverAngularVelocity);
|
properties.setAngularVelocity(_serverAngularVelocity);
|
||||||
properties.setActionData(_serverActionData);
|
if (_entity->actionDataNeedsTransmit()) {
|
||||||
|
_entity->setActionDataNeedsTransmit(false);
|
||||||
|
properties.setActionData(_serverActionData);
|
||||||
|
}
|
||||||
|
|
||||||
// set the LastEdited of the properties but NOT the entity itself
|
// set the LastEdited of the properties but NOT the entity itself
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
|
@ -526,7 +533,7 @@ void EntityMotionState::clearIncomingDirtyFlags() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// virtual
|
// virtual
|
||||||
quint8 EntityMotionState::getSimulationPriority() const {
|
quint8 EntityMotionState::getSimulationPriority() const {
|
||||||
if (_entity) {
|
if (_entity) {
|
||||||
return _entity->getSimulationPriority();
|
return _entity->getSimulationPriority();
|
||||||
|
|
|
@ -130,6 +130,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
auto ownerEntity = _ownerEntity.lock();
|
||||||
if (ownerEntity) {
|
if (ownerEntity) {
|
||||||
ownerEntity->setActionDataDirty(true);
|
ownerEntity->setActionDataDirty(true);
|
||||||
|
ownerEntity->setActionDataNeedsTransmit(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
activateBody();
|
activateBody();
|
||||||
|
|
|
@ -163,6 +163,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
||||||
auto ownerEntity = _ownerEntity.lock();
|
auto ownerEntity = _ownerEntity.lock();
|
||||||
if (ownerEntity) {
|
if (ownerEntity) {
|
||||||
ownerEntity->setActionDataDirty(true);
|
ownerEntity->setActionDataDirty(true);
|
||||||
|
ownerEntity->setActionDataNeedsTransmit(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
activateBody();
|
activateBody();
|
||||||
|
|
|
@ -501,8 +501,10 @@ void Model::setVisibleInScene(bool newValue, std::shared_ptr<render::Scene> scen
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges, bool showCollisionHull) {
|
||||||
if (!_meshGroupsKnown && isLoaded()) {
|
|
||||||
|
if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) {
|
||||||
|
_showCollisionHull = showCollisionHull;
|
||||||
segregateMeshGroups();
|
segregateMeshGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -525,8 +527,12 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChan
|
||||||
return somethingAdded;
|
return somethingAdded;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters) {
|
bool Model::addToScene(std::shared_ptr<render::Scene> scene,
|
||||||
if (!_meshGroupsKnown && isLoaded()) {
|
render::PendingChanges& pendingChanges,
|
||||||
|
render::Item::Status::Getters& statusGetters,
|
||||||
|
bool showCollisionHull) {
|
||||||
|
if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) {
|
||||||
|
_showCollisionHull = showCollisionHull;
|
||||||
segregateMeshGroups();
|
segregateMeshGroups();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1139,8 +1145,14 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Model::segregateMeshGroups() {
|
void Model::segregateMeshGroups() {
|
||||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
QSharedPointer<NetworkGeometry> networkGeometry;
|
||||||
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = _geometry->getMeshes();
|
if (_showCollisionHull && _collisionGeometry && _collisionGeometry->isLoaded()) {
|
||||||
|
networkGeometry = _collisionGeometry;
|
||||||
|
} else {
|
||||||
|
networkGeometry = _geometry;
|
||||||
|
}
|
||||||
|
const FBXGeometry& geometry = networkGeometry->getFBXGeometry();
|
||||||
|
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = networkGeometry->getMeshes();
|
||||||
|
|
||||||
_rig->makeAnimSkeleton(geometry);
|
_rig->makeAnimSkeleton(geometry);
|
||||||
|
|
||||||
|
|
|
@ -76,10 +76,13 @@ public:
|
||||||
return !_needsReload && isRenderable() && isActive() && isLoaded();
|
return !_needsReload && isRenderable() && isActive() && isLoaded();
|
||||||
}
|
}
|
||||||
bool initWhenReady(render::ScenePointer scene);
|
bool initWhenReady(render::ScenePointer scene);
|
||||||
bool addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
|
||||||
bool addToScene(std::shared_ptr<render::Scene> scene,
|
bool addToScene(std::shared_ptr<render::Scene> scene,
|
||||||
render::PendingChanges& pendingChanges,
|
render::PendingChanges& pendingChanges,
|
||||||
render::Item::Status::Getters& statusGetters);
|
bool showCollisionHull = false);
|
||||||
|
bool addToScene(std::shared_ptr<render::Scene> scene,
|
||||||
|
render::PendingChanges& pendingChanges,
|
||||||
|
render::Item::Status::Getters& statusGetters,
|
||||||
|
bool showCollisionHull = false);
|
||||||
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
void removeFromScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||||
void renderSetup(RenderArgs* args);
|
void renderSetup(RenderArgs* args);
|
||||||
bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().empty()); }
|
bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().empty()); }
|
||||||
|
@ -368,6 +371,7 @@ private:
|
||||||
bool _readyWhenAdded = false;
|
bool _readyWhenAdded = false;
|
||||||
bool _needsReload = true;
|
bool _needsReload = true;
|
||||||
bool _needsUpdateClusterMatrices = true;
|
bool _needsUpdateClusterMatrices = true;
|
||||||
|
bool _showCollisionHull = false;
|
||||||
|
|
||||||
friend class MeshPartPayload;
|
friend class MeshPartPayload;
|
||||||
protected:
|
protected:
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
#include "RenderDeferredTask.h"
|
#include "RenderDeferredTask.h"
|
||||||
|
|
||||||
#include <PerfStat.h>
|
#include <PerfStat.h>
|
||||||
|
#include <PathUtils.h>
|
||||||
#include <RenderArgs.h>
|
#include <RenderArgs.h>
|
||||||
#include <ViewFrustum.h>
|
#include <ViewFrustum.h>
|
||||||
#include <gpu/Context.h>
|
#include <gpu/Context.h>
|
||||||
|
@ -111,8 +112,11 @@ RenderDeferredTask::RenderDeferredTask() : Task() {
|
||||||
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false))));
|
_jobs.push_back(Job(new DepthSortItems::JobModel("DepthSortTransparent", _jobs.back().getOutput(), DepthSortItems(false))));
|
||||||
_jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput())));
|
_jobs.push_back(Job(new DrawTransparentDeferred::JobModel("TransparentDeferred", _jobs.back().getOutput())));
|
||||||
|
|
||||||
_jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques)));
|
// Grab a texture map representing the different status icons and assign that to the drawStatsuJob
|
||||||
|
auto iconMapPath = PathUtils::resourcesPath() + "icons/statusIconAtlas.svg";
|
||||||
|
|
||||||
|
auto statusIconMap = DependencyManager::get<TextureCache>()->getImageTexture(iconMapPath);
|
||||||
|
_jobs.push_back(Job(new render::DrawStatus::JobModel("DrawStatus", renderedOpaques, DrawStatus(statusIconMap))));
|
||||||
|
|
||||||
_jobs.back().setEnabled(false);
|
_jobs.back().setEnabled(false);
|
||||||
_drawStatusJobIndex = _jobs.size() - 1;
|
_drawStatusJobIndex = _jobs.size() - 1;
|
||||||
|
@ -387,4 +391,4 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
|
||||||
|
|
||||||
});
|
});
|
||||||
args->_batch = nullptr;
|
args->_batch = nullptr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -97,7 +97,12 @@ public:
|
||||||
int _drawStatusJobIndex = -1;
|
int _drawStatusJobIndex = -1;
|
||||||
int _drawHitEffectJobIndex = -1;
|
int _drawHitEffectJobIndex = -1;
|
||||||
|
|
||||||
void setDrawItemStatus(bool draw) { if (_drawStatusJobIndex >= 0) { _jobs[_drawStatusJobIndex].setEnabled(draw); } }
|
void setDrawItemStatus(int draw) {
|
||||||
|
if (_drawStatusJobIndex >= 0) {
|
||||||
|
_jobs[_drawStatusJobIndex].setEnabled(draw > 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } }
|
bool doDrawItemStatus() const { if (_drawStatusJobIndex >= 0) { return _jobs[_drawStatusJobIndex].isEnabled(); } else { return false; } }
|
||||||
|
|
||||||
void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } }
|
void setDrawHitEffect(bool draw) { if (_drawHitEffectJobIndex >= 0) { _jobs[_drawHitEffectJobIndex].setEnabled(draw); } }
|
||||||
|
|
|
@ -29,7 +29,7 @@ using namespace render;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() {
|
const gpu::PipelinePointer DrawStatus::getDrawItemBoundsPipeline() {
|
||||||
if (!_drawItemBoundsPipeline) {
|
if (!_drawItemBoundsPipeline) {
|
||||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert)));
|
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert)));
|
||||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag)));
|
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag)));
|
||||||
|
@ -56,18 +56,20 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() {
|
||||||
return _drawItemBoundsPipeline;
|
return _drawItemBoundsPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() {
|
const gpu::PipelinePointer DrawStatus::getDrawItemStatusPipeline() {
|
||||||
if (!_drawItemStatusPipeline) {
|
if (!_drawItemStatusPipeline) {
|
||||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert)));
|
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert)));
|
||||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag)));
|
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag)));
|
||||||
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||||
|
|
||||||
gpu::Shader::BindingSet slotBindings;
|
gpu::Shader::BindingSet slotBindings;
|
||||||
|
slotBindings.insert(gpu::Shader::Binding(std::string("iconStatusMap"), 0));
|
||||||
gpu::Shader::makeProgram(*program, slotBindings);
|
gpu::Shader::makeProgram(*program, slotBindings);
|
||||||
|
|
||||||
_drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos");
|
_drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos");
|
||||||
_drawItemStatusDimLoc = program->getUniforms().findLocation("inBoundDim");
|
_drawItemStatusDimLoc = program->getUniforms().findLocation("inBoundDim");
|
||||||
_drawItemStatusValueLoc = program->getUniforms().findLocation("inStatus");
|
_drawItemStatusValue0Loc = program->getUniforms().findLocation("inStatus0");
|
||||||
|
_drawItemStatusValue1Loc = program->getUniforms().findLocation("inStatus1");
|
||||||
|
|
||||||
auto state = std::make_shared<gpu::State>();
|
auto state = std::make_shared<gpu::State>();
|
||||||
|
|
||||||
|
@ -84,11 +86,23 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() {
|
||||||
return _drawItemStatusPipeline;
|
return _drawItemStatusPipeline;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems) {
|
void DrawStatus::setStatusIconMap(const gpu::TexturePointer& map) {
|
||||||
|
_statusIconMap = map;
|
||||||
|
}
|
||||||
|
|
||||||
|
const gpu::TexturePointer DrawStatus::getStatusIconMap() const {
|
||||||
|
return _statusIconMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawStatus::run(const SceneContextPointer& sceneContext,
|
||||||
|
const RenderContextPointer& renderContext,
|
||||||
|
const ItemIDsBounds& inItems) {
|
||||||
assert(renderContext->args);
|
assert(renderContext->args);
|
||||||
assert(renderContext->args->_viewFrustum);
|
assert(renderContext->args->_viewFrustum);
|
||||||
RenderArgs* args = renderContext->args;
|
RenderArgs* args = renderContext->args;
|
||||||
auto& scene = sceneContext->_scene;
|
auto& scene = sceneContext->_scene;
|
||||||
|
const int NUM_STATUS_VEC4_PER_ITEM = 2;
|
||||||
|
const int VEC4_LENGTH = 4;
|
||||||
|
|
||||||
// FIrst thing, we collect the bound and the status for all the items we want to render
|
// FIrst thing, we collect the bound and the status for all the items we want to render
|
||||||
int nbItems = 0;
|
int nbItems = 0;
|
||||||
|
@ -101,7 +115,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
||||||
}
|
}
|
||||||
|
|
||||||
_itemBounds->resize((inItems.size() * sizeof(AABox)));
|
_itemBounds->resize((inItems.size() * sizeof(AABox)));
|
||||||
_itemStatus->resize((inItems.size() * sizeof(glm::vec4)));
|
_itemStatus->resize((inItems.size() * NUM_STATUS_VEC4_PER_ITEM * sizeof(glm::vec4)));
|
||||||
AABox* itemAABox = reinterpret_cast<AABox*> (_itemBounds->editData());
|
AABox* itemAABox = reinterpret_cast<AABox*> (_itemBounds->editData());
|
||||||
glm::ivec4* itemStatus = reinterpret_cast<glm::ivec4*> (_itemStatus->editData());
|
glm::ivec4* itemStatus = reinterpret_cast<glm::ivec4*> (_itemStatus->editData());
|
||||||
for (auto& item : inItems) {
|
for (auto& item : inItems) {
|
||||||
|
@ -112,11 +126,31 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
||||||
(*itemAABox).setBox(item.bounds.getCorner(), 0.1f);
|
(*itemAABox).setBox(item.bounds.getCorner(), 0.1f);
|
||||||
}
|
}
|
||||||
auto& itemScene = scene->getItem(item.id);
|
auto& itemScene = scene->getItem(item.id);
|
||||||
(*itemStatus) = itemScene.getStatusPackedValues();
|
|
||||||
|
auto itemStatusPointer = itemScene.getStatus();
|
||||||
|
if (itemStatusPointer) {
|
||||||
|
// Query the current status values, this is where the statusGetter lambda get called
|
||||||
|
auto&& currentStatusValues = itemStatusPointer->getCurrentValues();
|
||||||
|
int valueNum = 0;
|
||||||
|
for (int vec4Num = 0; vec4Num < NUM_STATUS_VEC4_PER_ITEM; vec4Num++) {
|
||||||
|
(*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData());
|
||||||
|
for (int component = 0; component < VEC4_LENGTH; component++) {
|
||||||
|
valueNum = vec4Num * VEC4_LENGTH + component;
|
||||||
|
if (valueNum < (int)currentStatusValues.size()) {
|
||||||
|
(*itemStatus)[component] = currentStatusValues[valueNum].getPackedData();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
itemStatus++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
(*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData());
|
||||||
|
itemStatus++;
|
||||||
|
(*itemStatus) = glm::ivec4(Item::Status::Value::INVALID.getPackedData());
|
||||||
|
itemStatus++;
|
||||||
|
}
|
||||||
|
|
||||||
nbItems++;
|
nbItems++;
|
||||||
itemAABox++;
|
itemAABox++;
|
||||||
itemStatus++;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,6 +165,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
||||||
Transform viewMat;
|
Transform viewMat;
|
||||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||||
args->_viewFrustum->evalViewTransform(viewMat);
|
args->_viewFrustum->evalViewTransform(viewMat);
|
||||||
|
batch.setViewportTransform(args->_viewport);
|
||||||
|
|
||||||
batch.setProjectionTransform(projMat);
|
batch.setProjectionTransform(projMat);
|
||||||
batch.setViewTransform(viewMat);
|
batch.setViewTransform(viewMat);
|
||||||
|
@ -144,20 +179,28 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
||||||
|
|
||||||
const unsigned int VEC3_ADRESS_OFFSET = 3;
|
const unsigned int VEC3_ADRESS_OFFSET = 3;
|
||||||
|
|
||||||
for (int i = 0; i < nbItems; i++) {
|
if ((renderContext->_drawItemStatus & showDisplayStatusFlag) > 0) {
|
||||||
batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i));
|
for (int i = 0; i < nbItems; i++) {
|
||||||
batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET);
|
batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i));
|
||||||
|
batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET);
|
||||||
|
|
||||||
batch.draw(gpu::LINES, 24, 0);
|
batch.draw(gpu::LINES, 24, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
batch.setResourceTexture(0, gpu::TextureView(getStatusIconMap(), 0));
|
||||||
|
|
||||||
batch.setPipeline(getDrawItemStatusPipeline());
|
batch.setPipeline(getDrawItemStatusPipeline());
|
||||||
for (int i = 0; i < nbItems; i++) {
|
|
||||||
batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i));
|
|
||||||
batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET);
|
|
||||||
batch._glUniform4iv(_drawItemStatusValueLoc, 1, (const int*) (itemStatus + i));
|
|
||||||
|
|
||||||
batch.draw(gpu::TRIANGLES, 24, 0);
|
if ((renderContext->_drawItemStatus & showNetworkStatusFlag) > 0) {
|
||||||
|
for (int i = 0; i < nbItems; i++) {
|
||||||
|
batch._glUniform3fv(_drawItemStatusPosLoc, 1, (const float*) (itemAABox + i));
|
||||||
|
batch._glUniform3fv(_drawItemStatusDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET);
|
||||||
|
batch._glUniform4iv(_drawItemStatusValue0Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i));
|
||||||
|
batch._glUniform4iv(_drawItemStatusValue1Loc, 1, (const int*)(itemStatus + NUM_STATUS_VEC4_PER_ITEM * i + 1));
|
||||||
|
batch.draw(gpu::TRIANGLES, 24 * NUM_STATUS_VEC4_PER_ITEM, 0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
batch.setResourceTexture(0, 0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,22 +21,30 @@ namespace render {
|
||||||
int _drawItemBoundDimLoc = -1;
|
int _drawItemBoundDimLoc = -1;
|
||||||
int _drawItemStatusPosLoc = -1;
|
int _drawItemStatusPosLoc = -1;
|
||||||
int _drawItemStatusDimLoc = -1;
|
int _drawItemStatusDimLoc = -1;
|
||||||
int _drawItemStatusValueLoc = -1;
|
int _drawItemStatusValue0Loc = -1;
|
||||||
|
int _drawItemStatusValue1Loc = -1;
|
||||||
|
|
||||||
gpu::Stream::FormatPointer _drawItemFormat;
|
gpu::Stream::FormatPointer _drawItemFormat;
|
||||||
gpu::PipelinePointer _drawItemBoundsPipeline;
|
gpu::PipelinePointer _drawItemBoundsPipeline;
|
||||||
gpu::PipelinePointer _drawItemStatusPipeline;
|
gpu::PipelinePointer _drawItemStatusPipeline;
|
||||||
gpu::BufferPointer _itemBounds;
|
gpu::BufferPointer _itemBounds;
|
||||||
gpu::BufferPointer _itemStatus;
|
gpu::BufferPointer _itemStatus;
|
||||||
|
gpu::TexturePointer _statusIconMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
DrawStatus() {}
|
||||||
|
DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); }
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
||||||
|
|
||||||
typedef Job::ModelI<DrawStatus, ItemIDsBounds> JobModel;
|
typedef Job::ModelI<DrawStatus, ItemIDsBounds> JobModel;
|
||||||
|
|
||||||
const gpu::PipelinePointer& getDrawItemBoundsPipeline();
|
const gpu::PipelinePointer getDrawItemBoundsPipeline();
|
||||||
const gpu::PipelinePointer& getDrawItemStatusPipeline();
|
const gpu::PipelinePointer getDrawItemStatusPipeline();
|
||||||
|
|
||||||
|
void setStatusIconMap(const gpu::TexturePointer& map);
|
||||||
|
const gpu::TexturePointer getStatusIconMap() const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -143,7 +143,7 @@ public:
|
||||||
|
|
||||||
const Varying getInput() const { return _input; }
|
const Varying getInput() const { return _input; }
|
||||||
|
|
||||||
ModelI(const std::string& name, const Varying& input): Concept(name), _input(input) {}
|
ModelI(const std::string& name, const Varying& input, Data data = Data()) : Concept(name), _data(data), _input(input) {}
|
||||||
ModelI(const std::string& name, Data data): Concept(name), _data(data) {}
|
ModelI(const std::string& name, Data data): Concept(name), _data(data) {}
|
||||||
|
|
||||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||||
|
|
|
@ -25,6 +25,10 @@ public:
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr<SceneContext> SceneContextPointer;
|
typedef std::shared_ptr<SceneContext> SceneContextPointer;
|
||||||
|
|
||||||
|
// see examples/utilities/tools/renderEngineDebug.js
|
||||||
|
const int showDisplayStatusFlag = 1;
|
||||||
|
const int showNetworkStatusFlag = 2;
|
||||||
|
|
||||||
|
|
||||||
class RenderContext {
|
class RenderContext {
|
||||||
public:
|
public:
|
||||||
|
@ -49,7 +53,7 @@ public:
|
||||||
int _numDrawnOverlay3DItems = 0;
|
int _numDrawnOverlay3DItems = 0;
|
||||||
int _maxDrawnOverlay3DItems = -1;
|
int _maxDrawnOverlay3DItems = -1;
|
||||||
|
|
||||||
bool _drawItemStatus = false;
|
int _drawItemStatus = 0;
|
||||||
bool _drawHitEffect = false;
|
bool _drawHitEffect = false;
|
||||||
|
|
||||||
bool _occlusionStatus = false;
|
bool _occlusionStatus = false;
|
||||||
|
|
|
@ -72,17 +72,20 @@ void Item::Status::Value::setScale(float scale) {
|
||||||
void Item::Status::Value::setColor(float hue) {
|
void Item::Status::Value::setColor(float hue) {
|
||||||
// Convert the HUe from range [0, 360] to signed normalized value
|
// Convert the HUe from range [0, 360] to signed normalized value
|
||||||
const float HUE_MAX = 360.0f;
|
const float HUE_MAX = 360.0f;
|
||||||
_color = (std::numeric_limits<unsigned short>::max() - 1) * 0.5f * (1.0f + std::max(std::min(hue, HUE_MAX), 0.0f) / HUE_MAX);
|
_color = (std::numeric_limits<unsigned char>::max()) * (std::max(std::min(hue, HUE_MAX), 0.0f) / HUE_MAX);
|
||||||
|
}
|
||||||
|
void Item::Status::Value::setIcon(unsigned char icon) {
|
||||||
|
_icon = icon;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::Status::getPackedValues(glm::ivec4& values) const {
|
Item::Status::Values Item::Status::getCurrentValues() const {
|
||||||
for (unsigned int i = 0; i < (unsigned int)values.length(); i++) {
|
Values currentValues(_values.size());
|
||||||
if (i < _values.size()) {
|
auto currentValue = currentValues.begin();
|
||||||
values[i] = _values[i]().getPackedData();
|
for (auto& getter : _values) {
|
||||||
} else {
|
(*currentValue) = getter();
|
||||||
values[i] = Value::INVALID.getPackedData();
|
currentValue++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return currentValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Item::PayloadInterface::addStatusGetter(const Status::Getter& getter) {
|
void Item::PayloadInterface::addStatusGetter(const Status::Getter& getter) {
|
||||||
|
@ -110,15 +113,6 @@ void Item::resetPayload(const PayloadPointer& payload) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::ivec4 Item::getStatusPackedValues() const {
|
|
||||||
glm::ivec4 values(Status::Value::INVALID.getPackedData());
|
|
||||||
auto& status = getStatus();
|
|
||||||
if (status) {
|
|
||||||
status->getPackedValues(values);
|
|
||||||
};
|
|
||||||
return values;
|
|
||||||
}
|
|
||||||
|
|
||||||
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) {
|
||||||
_resetItems.push_back(id);
|
_resetItems.push_back(id);
|
||||||
_resetPayloads.push_back(payload);
|
_resetPayloads.push_back(payload);
|
||||||
|
|
|
@ -206,17 +206,21 @@ public:
|
||||||
// It can be scaled in the range [0, 1] and the color hue in the range [0, 360] representing the color wheel hue
|
// It can be scaled in the range [0, 1] and the color hue in the range [0, 360] representing the color wheel hue
|
||||||
class Value {
|
class Value {
|
||||||
unsigned short _scale = 0xFFFF;
|
unsigned short _scale = 0xFFFF;
|
||||||
unsigned short _color = 0xFFFF;
|
unsigned char _color = 0xFF;
|
||||||
|
unsigned char _icon = 0xFF;
|
||||||
public:
|
public:
|
||||||
const static Value INVALID; // Invalid value meanss the status won't show
|
const static Value INVALID; // Invalid value meanss the status won't show
|
||||||
|
|
||||||
Value() {}
|
Value() {}
|
||||||
Value(float scale, float hue) { setScale(scale); setColor(hue); }
|
Value(float scale, float hue, unsigned char icon = 0xFF) { setScale(scale); setColor(hue); setIcon(icon); }
|
||||||
|
|
||||||
// It can be scaled in the range [0, 1]
|
// It can be scaled in the range [0, 1]
|
||||||
void setScale(float scale);
|
void setScale(float scale);
|
||||||
// the color hue in the range [0, 360] representing the color wheel hue
|
// the color hue in the range [0, 360] representing the color wheel hue
|
||||||
void setColor(float hue);
|
void setColor(float hue);
|
||||||
|
// the icon to display in the range [0, 255], where 0 means no icon, just filled quad and anything else would
|
||||||
|
// hopefully have an icon available to display (see DrawStatusJob)
|
||||||
|
void setIcon(unsigned char icon);
|
||||||
|
|
||||||
// Standard color Hue
|
// Standard color Hue
|
||||||
static const float RED; // 0.0f;
|
static const float RED; // 0.0f;
|
||||||
|
@ -237,7 +241,10 @@ public:
|
||||||
|
|
||||||
void addGetter(const Getter& getter) { _values.push_back(getter); }
|
void addGetter(const Getter& getter) { _values.push_back(getter); }
|
||||||
|
|
||||||
void getPackedValues(glm::ivec4& values) const;
|
size_t getNumValues() const { return _values.size(); }
|
||||||
|
|
||||||
|
using Values = std::vector <Value>;
|
||||||
|
Values getCurrentValues() const;
|
||||||
};
|
};
|
||||||
typedef std::shared_ptr<Status> StatusPointer;
|
typedef std::shared_ptr<Status> StatusPointer;
|
||||||
|
|
||||||
|
@ -301,7 +308,6 @@ public:
|
||||||
|
|
||||||
// Access the status
|
// Access the status
|
||||||
const StatusPointer& getStatus() const { return _payload->getStatus(); }
|
const StatusPointer& getStatus() const { return _payload->getStatus(); }
|
||||||
glm::ivec4 getStatusPackedValues() const;
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
PayloadPointer _payload;
|
PayloadPointer _payload;
|
||||||
|
|
|
@ -12,9 +12,20 @@
|
||||||
//
|
//
|
||||||
|
|
||||||
in vec4 varColor;
|
in vec4 varColor;
|
||||||
|
in vec3 varTexcoord;
|
||||||
out vec4 outFragColor;
|
out vec4 outFragColor;
|
||||||
|
|
||||||
|
uniform sampler2D _icons;
|
||||||
|
vec2 getIconTexcoord(float icon, vec2 uv) {
|
||||||
|
const vec2 ICON_COORD_SIZE = vec2(0.0625, 1.0);
|
||||||
|
return vec2((uv.x + icon) * ICON_COORD_SIZE.x, uv.y * ICON_COORD_SIZE.y);
|
||||||
|
}
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
outFragColor = varColor;
|
if (varTexcoord.z < 254.5) {
|
||||||
|
outFragColor = texture(_icons, getIconTexcoord(varTexcoord.z, varTexcoord.xy)) * varColor;
|
||||||
|
} else {
|
||||||
|
vec2 centerDir = varTexcoord.xy * 2.0f - 1.0f;
|
||||||
|
outFragColor = vec4(varColor.xyz, 1.0 - step(1.0f, dot(centerDir.xy, centerDir.xy)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,10 +17,12 @@
|
||||||
<$declareStandardTransform()$>
|
<$declareStandardTransform()$>
|
||||||
|
|
||||||
out vec4 varColor;
|
out vec4 varColor;
|
||||||
|
out vec3 varTexcoord;
|
||||||
|
|
||||||
uniform vec3 inBoundPos;
|
uniform vec3 inBoundPos;
|
||||||
uniform vec3 inBoundDim;
|
uniform vec3 inBoundDim;
|
||||||
uniform ivec4 inStatus;
|
uniform ivec4 inStatus0;
|
||||||
|
uniform ivec4 inStatus1;
|
||||||
|
|
||||||
vec3 paintRainbow(float normalizedHue) {
|
vec3 paintRainbow(float normalizedHue) {
|
||||||
float v = normalizedHue * 6.f;
|
float v = normalizedHue * 6.f;
|
||||||
|
@ -43,16 +45,28 @@ vec3 paintRainbow(float normalizedHue) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vec2 unpackStatus(int v) {
|
const int INVALID_STATUS = int(0xFFFFFFFF);
|
||||||
return vec2(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0),
|
const int MAX_NUM_ICONS = 8;
|
||||||
clamp(float(int((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0));
|
const int ICONS_PER_ROW = 4;
|
||||||
|
|
||||||
|
int getIconStatus(int icon) {
|
||||||
|
if (icon < ICONS_PER_ROW) {
|
||||||
|
return inStatus0[icon];
|
||||||
|
} else if (icon < MAX_NUM_ICONS) {
|
||||||
|
return inStatus1[icon - ICONS_PER_ROW];
|
||||||
|
}
|
||||||
|
return INVALID_STATUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
vec3 unpackStatus(int v) {
|
||||||
|
return vec3(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0),
|
||||||
|
clamp(float(uint((v >> 16) & 0xFF)) / 255.0, 0.0, 1.0),
|
||||||
|
clamp(float(int((v >> 24) & 0xFF)), 0.0, 255.0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
const vec2 ICON_PIXEL_SIZE = vec2(10, 10);
|
const int NUM_VERTICES_PER_ICON = 6;
|
||||||
const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2);
|
const vec4 UNIT_QUAD[NUM_VERTICES_PER_ICON] = vec4[NUM_VERTICES_PER_ICON](
|
||||||
const int NUM_VERTICES = 6;
|
|
||||||
const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES](
|
|
||||||
vec4(-1.0, -1.0, 0.0, 1.0),
|
vec4(-1.0, -1.0, 0.0, 1.0),
|
||||||
vec4(1.0, -1.0, 0.0, 1.0),
|
vec4(1.0, -1.0, 0.0, 1.0),
|
||||||
vec4(-1.0, 1.0, 0.0, 1.0),
|
vec4(-1.0, 1.0, 0.0, 1.0),
|
||||||
|
@ -61,6 +75,17 @@ void main(void) {
|
||||||
vec4(1.0, 1.0, 0.0, 1.0)
|
vec4(1.0, 1.0, 0.0, 1.0)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const vec2 ICON_PIXEL_SIZE = vec2(20, 20);
|
||||||
|
const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2);
|
||||||
|
const vec2 ICON_GRID_SLOTS[MAX_NUM_ICONS] = vec2[MAX_NUM_ICONS](vec2(-1.5, 0.5),
|
||||||
|
vec2(-0.5, 0.5),
|
||||||
|
vec2(0.5, 0.5),
|
||||||
|
vec2(1.5, 0.5),
|
||||||
|
vec2(-1.5,-0.5),
|
||||||
|
vec2(-0.5,-0.5),
|
||||||
|
vec2(0.5, -0.5),
|
||||||
|
vec2(1.5, -0.5));
|
||||||
|
|
||||||
// anchor point in clip space
|
// anchor point in clip space
|
||||||
vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0);
|
vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0);
|
||||||
TransformCamera cam = getTransformCamera();
|
TransformCamera cam = getTransformCamera();
|
||||||
|
@ -68,36 +93,43 @@ void main(void) {
|
||||||
<$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$>
|
<$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$>
|
||||||
|
|
||||||
// Which icon are we dealing with ?
|
// Which icon are we dealing with ?
|
||||||
int iconNum = gl_VertexID / NUM_VERTICES;
|
int iconNum = gl_VertexID / NUM_VERTICES_PER_ICON;
|
||||||
|
int packedIconStatus = getIconStatus(iconNum);
|
||||||
|
|
||||||
// if invalid, just kill
|
// if invalid, just kill
|
||||||
if (inStatus[iconNum] == 0xFFFFFFFF) {
|
if (packedIconStatus == INVALID_STATUS) {
|
||||||
gl_Position = anchorPoint;
|
gl_Position = anchorPoint;
|
||||||
varColor = vec4(1.0);
|
varColor = vec4(1.0);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Which quad vertex pos?
|
||||||
|
int twoTriID = gl_VertexID - iconNum * NUM_VERTICES_PER_ICON;
|
||||||
|
vec4 quadPos = UNIT_QUAD[twoTriID];
|
||||||
|
|
||||||
// unpack to get x and y satus
|
// unpack to get x and y satus
|
||||||
vec2 iconStatus = unpackStatus(inStatus[iconNum]);
|
vec3 iconStatus = unpackStatus(packedIconStatus);
|
||||||
|
|
||||||
// Use the status for showing a color
|
// Use the status for showing a color
|
||||||
varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0);
|
varColor = vec4(paintRainbow(abs(iconStatus.y)), 1.0);
|
||||||
|
|
||||||
|
// Pass the texcoord and the z texcoord is representing the texture icon
|
||||||
|
varTexcoord = vec3((quadPos.xy + 1.0) * 0.5, iconStatus.z);
|
||||||
|
|
||||||
// Also changes the size of the notification
|
// Also changes the size of the notification
|
||||||
vec2 iconScale = ICON_PIXEL_SIZE;
|
vec2 iconScale = ICON_PIXEL_SIZE;
|
||||||
iconScale = max(vec2(1, 1), (iconScale * iconStatus.x));
|
iconScale = max(vec2(0, 0), (iconScale * iconStatus.x));
|
||||||
|
|
||||||
//Offset icon to the right based on the iconNum
|
//Offset icon to the right based on the iconNum
|
||||||
vec2 offset = vec2(iconNum * (ICON_PIXEL_SIZE.x + MARGIN_PIXEL_SIZE.x), 0);
|
vec2 gridOffset = ICON_GRID_SLOTS[iconNum];
|
||||||
|
vec2 offset = gridOffset * (ICON_PIXEL_SIZE + MARGIN_PIXEL_SIZE);
|
||||||
|
|
||||||
// Final position in pixel space
|
// Final position in pixel space
|
||||||
int twoTriID = gl_VertexID - iconNum * NUM_VERTICES;
|
vec2 quadPixelPos = offset.xy + quadPos.xy * 0.5 * iconScale;
|
||||||
vec4 pos = UNIT_QUAD[twoTriID];
|
|
||||||
vec2 quadPixelPos = offset.xy + pos.xy * 0.5 * iconScale;
|
|
||||||
|
|
||||||
vec4 viewport;
|
vec4 viewport;
|
||||||
<$transformCameraViewport(cam, viewport)$>;
|
<$transformCameraViewport(cam, viewport)$>;
|
||||||
vec2 pixelToClip = vec2(2.0 / viewport.z, 2.0 / viewport.w);
|
vec2 pixelToClip = vec2(2.0 / viewport.z, 2.0 / viewport.w);
|
||||||
gl_Position = anchorPoint + (anchorPoint.w * vec4(quadPixelPos * pixelToClip, 0.0, 0.0));
|
gl_Position = anchorPoint + (anchorPoint.w * vec4(quadPixelPos * pixelToClip, 0.0, 0.0));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -107,8 +107,8 @@ public:
|
||||||
Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; }
|
Q_INVOKABLE void setEngineMaxDrawnOverlay3DItems(int count) { _maxDrawnOverlay3DItems = count; }
|
||||||
Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; }
|
Q_INVOKABLE int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; }
|
||||||
|
|
||||||
Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; }
|
Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; }
|
||||||
Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; }
|
Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; }
|
||||||
|
|
||||||
Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; }
|
Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; }
|
||||||
Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; }
|
Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; }
|
||||||
|
@ -143,7 +143,7 @@ protected:
|
||||||
int _maxDrawnTransparentItems = -1;
|
int _maxDrawnTransparentItems = -1;
|
||||||
int _maxDrawnOverlay3DItems = -1;
|
int _maxDrawnOverlay3DItems = -1;
|
||||||
|
|
||||||
bool _drawItemStatus = false;
|
int _drawItemStatus = 0;
|
||||||
|
|
||||||
bool _drawHitEffect = false;
|
bool _drawHitEffect = false;
|
||||||
|
|
||||||
|
|
|
@ -68,17 +68,16 @@ public:
|
||||||
class RenderArgs {
|
class RenderArgs {
|
||||||
public:
|
public:
|
||||||
typedef std::function<bool(const RenderArgs* args, const AABox& bounds)> ShoudRenderFunctor;
|
typedef std::function<bool(const RenderArgs* args, const AABox& bounds)> ShoudRenderFunctor;
|
||||||
|
|
||||||
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE };
|
enum RenderMode { DEFAULT_RENDER_MODE, SHADOW_RENDER_MODE, DIFFUSE_RENDER_MODE, NORMAL_RENDER_MODE, MIRROR_RENDER_MODE };
|
||||||
|
|
||||||
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
enum RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
||||||
|
|
||||||
enum DebugFlags {
|
enum DebugFlags {
|
||||||
RENDER_DEBUG_NONE = 0,
|
RENDER_DEBUG_NONE = 0,
|
||||||
RENDER_DEBUG_HULLS = 1,
|
RENDER_DEBUG_HULLS = 1
|
||||||
RENDER_DEBUG_SIMULATION_OWNERSHIP = 2,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
|
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
|
||||||
OctreeRenderer* renderer = nullptr,
|
OctreeRenderer* renderer = nullptr,
|
||||||
ViewFrustum* viewFrustum = nullptr,
|
ViewFrustum* viewFrustum = nullptr,
|
||||||
|
|
Loading…
Reference in a new issue