mirror of
https://github.com/lubosz/overte.git
synced 2025-04-23 20:34:07 +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 "OctreeServer.h"
|
||||
#include "OctreeServerConsts.h"
|
||||
#include "OctreeLogging.h"
|
||||
|
||||
quint64 startSceneSleepTime = 0;
|
||||
quint64 endSceneSleepTime = 0;
|
||||
|
@ -572,14 +573,12 @@ int OctreeSendThread::packetDistributor(OctreeQueryNode* nodeData, bool viewFrus
|
|||
OctreeServer::trackInsideTime((float)elapsedInsideUsecs);
|
||||
}
|
||||
|
||||
|
||||
if (somethingToSend && _myServer->wantsVerboseDebug()) {
|
||||
qDebug() << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval
|
||||
<< " maxPacketsPerInterval = " << maxPacketsPerInterval
|
||||
<< " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval;
|
||||
qCDebug(octree) << "Hit PPS Limit, packetsSentThisInterval =" << packetsSentThisInterval
|
||||
<< " maxPacketsPerInterval = " << maxPacketsPerInterval
|
||||
<< " clientMaxPacketsPerInterval = " << clientMaxPacketsPerInterval;
|
||||
}
|
||||
|
||||
|
||||
// Here's where we can/should allow the server to send other data...
|
||||
// send the environment packet
|
||||
// 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) {
|
||||
data["gravity"] = grabbedProperties.gravity;
|
||||
data["ignoreForCollisions"] = grabbedProperties.ignoreForCollisions;
|
||||
data["collisionsWillMove"] = grabbedProperties.collisionsWillMove;
|
||||
var whileHeldProperties = {gravity: {x:0, y:0, z:0}};
|
||||
if (invertSolidWhileHeld) {
|
||||
whileHeldProperties["ignoreForCollisions"] = ! grabbedProperties.ignoreForCollisions;
|
||||
|
@ -522,7 +523,8 @@ Grabber.prototype.deactivateEntity = function(entityID) {
|
|||
if (data["refCount"] < 1) {
|
||||
Entities.editEntity(entityID, {
|
||||
gravity: data["gravity"],
|
||||
ignoreForCollisions: data["ignoreForCollisions"]
|
||||
ignoreForCollisions: data["ignoreForCollisions"],
|
||||
collisionsWillMove: data["collisionsWillMove"]
|
||||
});
|
||||
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",
|
||||
function(value) { Scene.setEngineDisplayItemStatus(value); },
|
||||
function() { return Scene.doEngineDisplayItemStatus(); },
|
||||
function(value) { return (value); }
|
||||
// see libraries/render/src/render/Engine.h
|
||||
var showDisplayStatusFlag = 1;
|
||||
var showNetworkStatusFlag = 2;
|
||||
|
||||
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;
|
||||
|
|
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)) {
|
||||
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;
|
||||
//ViveControllerManager::getInstance().updateRendering(renderArgs, _main3DScene, pendingChanges);
|
||||
}
|
||||
|
@ -3562,6 +3558,9 @@ void Application::displaySide(RenderArgs* renderArgs, Camera& theCamera, bool se
|
|||
renderContext._maxDrawnOverlay3DItems = sceneInterface->getEngineMaxDrawnOverlay3DItems();
|
||||
|
||||
renderContext._drawItemStatus = sceneInterface->doEngineDisplayItemStatus();
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::PhysicsShowOwned)) {
|
||||
renderContext._drawItemStatus |= render::showNetworkStatusFlag;
|
||||
}
|
||||
renderContext._drawHitEffect = sceneInterface->doEngineDisplayHitEffect();
|
||||
|
||||
renderContext._occlusionStatus = Menu::getInstance()->isOptionChecked(MenuOption::DebugAmbientOcclusion);
|
||||
|
|
|
@ -212,6 +212,7 @@ bool AvatarActionHold::updateArguments(QVariantMap arguments) {
|
|||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <ObjectMotionState.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "../render-utils/simple_vert.h"
|
||||
#include "../render-utils/simple_frag.h"
|
||||
|
||||
|
@ -63,6 +62,4 @@ void RenderableBoxEntityItem::render(RenderArgs* args) {
|
|||
} else {
|
||||
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"
|
||||
|
||||
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 <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 {
|
||||
public:
|
||||
RenderableEntityItemProxy(EntityItemPointer entity) : entity(entity) { }
|
||||
typedef render::Payload<RenderableEntityItemProxy> Payload;
|
||||
typedef Payload::DataPointer Pointer;
|
||||
|
||||
|
||||
EntityItemPointer entity;
|
||||
};
|
||||
|
||||
|
@ -36,19 +49,23 @@ class SimpleRenderableEntityItem {
|
|||
public:
|
||||
bool addToScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
_myItem = scene->allocateID();
|
||||
|
||||
|
||||
auto renderData = std::make_shared<RenderableEntityItemProxy>(self);
|
||||
auto renderPayload = std::make_shared<RenderableEntityItemProxy::Payload>(renderData);
|
||||
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(self, statusGetters);
|
||||
renderPayload->addStatusGetters(statusGetters);
|
||||
|
||||
pendingChanges.resetItem(_myItem, renderPayload);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void removeFromScene(EntityItemPointer self, std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges) {
|
||||
pendingChanges.removeItem(_myItem);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
render::ItemID _myItem;
|
||||
};
|
||||
|
@ -62,5 +79,4 @@ private: \
|
|||
SimpleRenderableEntityItem _renderHelper;
|
||||
|
||||
|
||||
|
||||
#endif // hifi_RenderableEntityItem_h
|
||||
|
|
|
@ -54,6 +54,4 @@ void RenderableLineEntityItem::render(RenderArgs* args) {
|
|||
DependencyManager::get<DeferredLightingEffect>()->bindSimpleProgram(batch);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||
}
|
||||
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
};
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#define hifi_RenderableLineEntityItem_h
|
||||
|
||||
#include <LineEntityItem.h>
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
#include <GeometryCache.h>
|
||||
|
||||
|
|
|
@ -21,7 +21,9 @@
|
|||
|
||||
#include "EntityTreeRenderer.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
EntityItemPointer RenderableModelEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& 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,
|
||||
render::PendingChanges& pendingChanges) {
|
||||
_myMetaItem = scene->allocateID();
|
||||
|
@ -209,11 +192,11 @@ bool RenderableModelEntityItem::addToScene(EntityItemPointer self, std::shared_p
|
|||
|
||||
if (_model) {
|
||||
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
|
||||
// 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;
|
||||
|
@ -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
|
||||
// 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;
|
||||
|
||||
_model->removeFromScene(scene, pendingChanges);
|
||||
|
||||
render::Item::Status::Getters statusGetters;
|
||||
makeEntityItemStatusGetters(this, statusGetters);
|
||||
_model->addToScene(scene, pendingChanges, statusGetters);
|
||||
makeEntityItemStatusGetters(shared_from_this(), statusGetters);
|
||||
_model->addToScene(scene, pendingChanges, statusGetters, _showCollisionHull);
|
||||
|
||||
scene->enqueuePendingChanges(pendingChanges);
|
||||
}
|
||||
|
@ -274,7 +259,7 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
EntityTreeRenderer* renderer = static_cast<EntityTreeRenderer*>(args->_renderer);
|
||||
getModel(renderer);
|
||||
}
|
||||
|
||||
|
||||
if (_model) {
|
||||
// handle animations..
|
||||
if (hasAnimation()) {
|
||||
|
@ -320,11 +305,12 @@ void RenderableModelEntityItem::render(RenderArgs* args) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
RenderableDebugableEntityItem::renderBoundingBox(this, args, 0.0f, greenColor);
|
||||
static glm::vec4 greenColor(0.0f, 1.0f, 0.0f, 1.0f);
|
||||
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) {
|
||||
|
|
|
@ -16,7 +16,6 @@
|
|||
#include <QStringList>
|
||||
|
||||
#include <ModelEntityItem.h>
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
|
||||
class Model;
|
||||
class EntityTreeRenderer;
|
||||
|
@ -82,6 +81,8 @@ private:
|
|||
bool _dimensionsInitialized = true;
|
||||
|
||||
render::ItemID _myMetaItem;
|
||||
|
||||
bool _showCollisionHull = false;
|
||||
};
|
||||
|
||||
#endif // hifi_RenderableModelEntityItem_h
|
||||
|
|
|
@ -139,6 +139,9 @@ bool RenderableParticleEffectEntityItem::addToScene(EntityItemPointer self,
|
|||
_renderItemId = scene->allocateID();
|
||||
auto renderData = ParticlePayload::Pointer(particlePayload);
|
||||
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);
|
||||
_scene = scene;
|
||||
return true;
|
||||
|
|
|
@ -153,6 +153,4 @@ void RenderablePolyLineEntityItem::render(RenderArgs* args) {
|
|||
batch.setInputBuffer(0, _verticesBuffer, 0, _format->getChannels().at(0)._stride);
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
};
|
||||
|
|
|
@ -14,7 +14,6 @@
|
|||
|
||||
#include <gpu/Batch.h>
|
||||
#include <PolyLineEntityItem.h>
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
#include <GeometryCache.h>
|
||||
#include <QReadWriteLock>
|
||||
|
|
|
@ -538,8 +538,6 @@ void RenderablePolyVoxEntityItem::render(RenderArgs* args) {
|
|||
batch._glUniform3f(voxelVolumeSizeLocation, _voxelVolumeSize.x, _voxelVolumeSize.y, _voxelVolumeSize.z);
|
||||
|
||||
batch.drawIndexed(gpu::TRIANGLES, mesh->getNumIndices(), 0);
|
||||
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
}
|
||||
|
||||
bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
||||
|
@ -551,6 +549,10 @@ bool RenderablePolyVoxEntityItem::addToScene(EntityItemPointer self,
|
|||
auto renderData = PolyVoxPayload::Pointer(renderItem);
|
||||
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);
|
||||
|
||||
return true;
|
||||
|
|
|
@ -21,7 +21,6 @@
|
|||
#include <TextureCache.h>
|
||||
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "RenderableEntityItem.h"
|
||||
#include "gpu/Context.h"
|
||||
|
||||
|
|
|
@ -20,7 +20,6 @@
|
|||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include "RenderableDebugableEntityItem.h"
|
||||
#include "../render-utils/simple_vert.h"
|
||||
#include "../render-utils/simple_frag.h"
|
||||
|
||||
|
@ -70,7 +69,4 @@ void RenderableSphereEntityItem::render(RenderArgs* args) {
|
|||
batch.setModelTransform(Transform());
|
||||
DependencyManager::get<DeferredLightingEffect>()->renderSolidSphereInstance(batch, modelTransform, sphereColor);
|
||||
}
|
||||
|
||||
|
||||
RenderableDebugableEntityItem::render(this, args);
|
||||
};
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
#include <GeometryCache.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
|
||||
// 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;
|
||||
|
@ -112,7 +114,9 @@ void RenderableZoneEntityItem::render(RenderArgs* args) {
|
|||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::PendingChanges 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);
|
||||
|
||||
|
@ -203,7 +207,11 @@ bool RenderableZoneEntityItem::addToScene(EntityItemPointer self, std::shared_pt
|
|||
|
||||
auto renderData = std::make_shared<RenderableZoneEntityItemMeta>(self);
|
||||
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);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -304,3 +304,24 @@ QDataStream& operator>>(QDataStream& stream, EntityActionType& entityActionType)
|
|||
entityActionType = (EntityActionType)actionTypeAsInt;
|
||||
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, EntityActionType& entityActionType);
|
||||
|
||||
QString serializedActionsToDebugString(QByteArray data);
|
||||
|
||||
#endif // hifi_EntityActionInterface_h
|
||||
|
|
|
@ -630,6 +630,9 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
dataAt += bytes;
|
||||
bytesRead += bytes;
|
||||
|
||||
if (wantTerseEditLogging() && _simulationOwner != newSimOwner) {
|
||||
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << newSimOwner;
|
||||
}
|
||||
if (_simulationOwner.set(newSimOwner)) {
|
||||
_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_HREF, QString, setHref);
|
||||
READ_ENTITY_PROPERTY(PROP_DESCRIPTION, QString, setDescription);
|
||||
|
||||
{ // 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;
|
||||
}
|
||||
READ_ENTITY_PROPERTY(PROP_ACTION_DATA, QByteArray, setActionData);
|
||||
|
||||
bytesRead += readEntitySubclassDataFromBuffer(dataAt, (bytesLeftToRead - bytesRead), args,
|
||||
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
|
||||
// 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);
|
||||
|
||||
|
||||
// we want to extrapolate the motion forward to compensate for packet travel time, but
|
||||
// we don't want the side effect of flag setting.
|
||||
simulateKinematicMotion(skipTimeForward, false);
|
||||
|
@ -745,7 +738,6 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
if (overwriteLocalData) {
|
||||
if (!_simulationOwner.matchesValidID(myNodeID)) {
|
||||
|
||||
_lastSimulated = now;
|
||||
}
|
||||
}
|
||||
|
@ -996,6 +988,11 @@ EntityTreePointer EntityItem::getTree() const {
|
|||
return tree;
|
||||
}
|
||||
|
||||
bool EntityItem::wantTerseEditLogging() {
|
||||
EntityTreePointer tree = getTree();
|
||||
return tree ? tree->wantTerseEditLogging() : false;
|
||||
}
|
||||
|
||||
glm::mat4 EntityItem::getEntityToWorldMatrix() const {
|
||||
glm::mat4 translation = glm::translate(getPosition());
|
||||
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) {
|
||||
if (wantTerseEditLogging() && (id != _simulationOwner.getID() || priority != _simulationOwner.getPriority())) {
|
||||
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << id << priority;
|
||||
}
|
||||
_simulationOwner.set(id, priority);
|
||||
}
|
||||
|
||||
void EntityItem::setSimulationOwner(const SimulationOwner& owner) {
|
||||
if (wantTerseEditLogging() && _simulationOwner != owner) {
|
||||
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << owner;
|
||||
}
|
||||
|
||||
_simulationOwner.set(owner);
|
||||
}
|
||||
|
||||
void EntityItem::updateSimulatorID(const QUuid& value) {
|
||||
if (wantTerseEditLogging() && _simulationOwner.getID() != value) {
|
||||
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now" << value;
|
||||
}
|
||||
|
||||
if (_simulationOwner.setID(value)) {
|
||||
_dirtyFlags |= Simulation::DIRTY_SIMULATOR_ID;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::clearSimulationOwnership() {
|
||||
if (wantTerseEditLogging() && !_simulationOwner.isNull()) {
|
||||
qCDebug(entities) << "sim ownership for" << getDebugName() << "is now null";
|
||||
}
|
||||
|
||||
_simulationOwner.clear();
|
||||
// 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
|
||||
|
@ -1607,6 +1619,7 @@ bool EntityItem::removeActionInternal(const QUuid& actionID, EntitySimulation* s
|
|||
bool success = true;
|
||||
serializeActions(success, _allActionsDataCache);
|
||||
_dirtyFlags |= Simulation::DIRTY_PHYSICS_ACTIVATION;
|
||||
setActionDataNeedsTransmit(true);
|
||||
return success;
|
||||
}
|
||||
return false;
|
||||
|
@ -1649,7 +1662,7 @@ void EntityItem::deserializeActionsInternal() {
|
|||
return;
|
||||
}
|
||||
|
||||
EntityTreePointer entityTree = _element ? _element->getTree() : nullptr;
|
||||
EntityTreePointer entityTree = getTree();
|
||||
assert(entityTree);
|
||||
EntitySimulation* simulation = entityTree ? entityTree->getSimulation() : nullptr;
|
||||
assert(simulation);
|
||||
|
@ -1770,6 +1783,7 @@ void EntityItem::serializeActions(bool& success, QByteArray& result) const {
|
|||
serializedActionsStream << serializedActions;
|
||||
|
||||
if (result.size() >= _maxActionsDataSize) {
|
||||
qDebug() << "EntityItem::serializeActions size is too large -- " << result.size() << ">=" << _maxActionsDataSize;
|
||||
success = false;
|
||||
return;
|
||||
}
|
||||
|
|
|
@ -307,6 +307,7 @@ public:
|
|||
|
||||
QString getName() const { return _name; }
|
||||
void setName(const QString& value) { _name = value; }
|
||||
QString getDebugName() { return _name != "" ? _name : getID().toString(); }
|
||||
|
||||
bool getVisible() const { return _visible; }
|
||||
void setVisible(bool value) { _visible = value; }
|
||||
|
@ -381,6 +382,7 @@ public:
|
|||
void setPhysicsInfo(void* data) { _physicsInfo = data; }
|
||||
EntityTreeElementPointer getElement() const { return _element; }
|
||||
EntityTreePointer getTree() const;
|
||||
bool wantTerseEditLogging();
|
||||
|
||||
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
|
||||
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
|
||||
|
@ -406,7 +408,13 @@ public:
|
|||
QList<QUuid> getActionIDs() { return _objectActions.keys(); }
|
||||
QVariantMap getActionArguments(const QUuid& actionID) const;
|
||||
void deserializeActions();
|
||||
|
||||
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;
|
||||
|
||||
void setSourceUUID(const QUuid& sourceUUID) { _sourceUUID = sourceUUID; }
|
||||
|
@ -439,7 +447,7 @@ protected:
|
|||
mutable bool _recalcAABox = true;
|
||||
mutable bool _recalcMinAACube = true;
|
||||
mutable bool _recalcMaxAACube = true;
|
||||
|
||||
|
||||
float _glowLevel;
|
||||
float _localRenderAlpha;
|
||||
float _density = ENTITY_ITEM_DEFAULT_DENSITY; // kg/m^3
|
||||
|
@ -510,6 +518,7 @@ protected:
|
|||
void checkWaitingToRemove(EntitySimulation* simulation = nullptr);
|
||||
mutable QSet<QUuid> _actionsToRemove;
|
||||
mutable bool _actionDataDirty = false;
|
||||
mutable bool _actionDataNeedsTransmit = false;
|
||||
// _previouslyDeletedActions is used to avoid an action being re-added due to server round-trip lag
|
||||
static quint64 _rememberDeletedActionTime;
|
||||
mutable QHash<QUuid, quint64> _previouslyDeletedActions;
|
||||
|
|
|
@ -611,7 +611,8 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
const QVariantMap& arguments) {
|
||||
QUuid actionID = QUuid::createUuid();
|
||||
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
|
||||
// case that a script adds an action immediately after an object is created, and the physicsInfo
|
||||
// is computed asynchronously.
|
||||
|
@ -623,16 +624,16 @@ QUuid EntityScriptingInterface::addAction(const QString& actionTypeString,
|
|||
return false;
|
||||
}
|
||||
EntityActionPointer action = actionFactory->factory(actionType, actionID, entity, arguments);
|
||||
if (action) {
|
||||
entity->addAction(simulation, action);
|
||||
auto nodeList = DependencyManager::get<NodeList>();
|
||||
const QUuid myNodeID = nodeList->getSessionUUID();
|
||||
if (entity->getSimulatorID() != myNodeID) {
|
||||
entity->flagForOwnership();
|
||||
}
|
||||
return true;
|
||||
if (!action) {
|
||||
return false;
|
||||
}
|
||||
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) {
|
||||
return actionID;
|
||||
|
@ -656,9 +657,12 @@ bool EntityScriptingInterface::updateAction(const QUuid& entityID, const QUuid&
|
|||
}
|
||||
|
||||
bool EntityScriptingInterface::deleteAction(const QUuid& entityID, const QUuid& actionID) {
|
||||
return actionWorker(entityID, [&](EntitySimulation* simulation, EntityItemPointer entity) {
|
||||
return entity->removeAction(simulation, actionID);
|
||||
bool success = false;
|
||||
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) {
|
||||
|
|
|
@ -198,6 +198,10 @@ bool EntityTree::updateEntityWithElement(EntityItemPointer entity, const EntityI
|
|||
properties.setVelocityChanged(false);
|
||||
properties.setAngularVelocityChanged(false);
|
||||
properties.setAccelerationChanged(false);
|
||||
|
||||
if (wantTerseEditLogging()) {
|
||||
qCDebug(entities) << senderNode->getUUID() << "physical edits suppressed";
|
||||
}
|
||||
}
|
||||
}
|
||||
// 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) {
|
||||
static quint64 lastTerseLog = 0;
|
||||
quint64 now = usecTimestampNow();
|
||||
|
||||
if (now - lastTerseLog > USECS_PER_SECOND) {
|
||||
qCDebug(entities) << "-------------------------";
|
||||
}
|
||||
lastTerseLog = now;
|
||||
|
||||
if (properties.simulationOwnerChanged()) {
|
||||
int simIndex = changedProperties.indexOf("simulationOwner");
|
||||
if (simIndex >= 0) {
|
||||
|
@ -619,6 +631,79 @@ void EntityTree::fixupTerseEditLogging(EntityItemProperties& properties, QList<Q
|
|||
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,
|
||||
|
@ -673,7 +758,8 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi
|
|||
if (wantTerseEditLogging()) {
|
||||
QList<QString> changedProperties = properties.listChangedProperties();
|
||||
fixupTerseEditLogging(properties, changedProperties);
|
||||
qCDebug(entities) << "edit" << entityItemID.toString() << changedProperties;
|
||||
qCDebug(entities) << senderNode->getUUID() << "edit" <<
|
||||
existingEntity->getDebugName() << changedProperties;
|
||||
}
|
||||
endLogging = usecTimestampNow();
|
||||
|
||||
|
@ -703,7 +789,7 @@ int EntityTree::processEditPacketData(NLPacket& packet, const unsigned char* edi
|
|||
if (wantTerseEditLogging()) {
|
||||
QList<QString> changedProperties = properties.listChangedProperties();
|
||||
fixupTerseEditLogging(properties, changedProperties);
|
||||
qCDebug(entities) << "add" << entityItemID.toString() << changedProperties;
|
||||
qCDebug(entities) << senderNode->getUUID() << "add" << entityItemID << changedProperties;
|
||||
}
|
||||
endLogging = usecTimestampNow();
|
||||
|
||||
|
|
|
@ -157,7 +157,7 @@ void SimulationOwner::test() {
|
|||
}
|
||||
|
||||
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) {
|
||||
|
|
|
@ -331,7 +331,7 @@ public:
|
|||
|
||||
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<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); }
|
||||
|
||||
// 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;
|
||||
} else {
|
||||
_nextOwnershipBid = usecTimestampNow() + USECS_BETWEEN_OWNERSHIP_BIDS;
|
||||
if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() > _outgoingPriority) {
|
||||
// we own the simulation or our priority looses to remote
|
||||
if (engine->getSessionID() == _entity->getSimulatorID() || _entity->getSimulationPriority() >= _outgoingPriority) {
|
||||
// we own the simulation or our priority looses to (or ties with) remote
|
||||
_outgoingPriority = NO_PRORITY;
|
||||
}
|
||||
}
|
||||
|
@ -244,7 +244,7 @@ bool EntityMotionState::isCandidateForOwnership(const QUuid& sessionID) const {
|
|||
return false;
|
||||
}
|
||||
assert(entityTreeIsLocked());
|
||||
return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID();
|
||||
return _outgoingPriority != NO_PRORITY || sessionID == _entity->getSimulatorID() || _entity->actionDataNeedsTransmit();
|
||||
}
|
||||
|
||||
bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
||||
|
@ -292,7 +292,7 @@ bool EntityMotionState::remoteSimulationOutOfSync(uint32_t simulationStep) {
|
|||
_serverPosition += dt * _serverVelocity;
|
||||
}
|
||||
|
||||
if (_serverActionData != _entity->getActionData()) {
|
||||
if (_entity->actionDataNeedsTransmit()) {
|
||||
setOutgoingPriority(SCRIPT_EDIT_SIMULATION_PRIORITY);
|
||||
return true;
|
||||
}
|
||||
|
@ -370,11 +370,15 @@ bool EntityMotionState::shouldSendUpdate(uint32_t simulationStep, const QUuid& s
|
|||
assert(_body);
|
||||
assert(entityTreeIsLocked());
|
||||
|
||||
if (_entity->actionDataNeedsTransmit()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (_entity->getSimulatorID() != sessionID) {
|
||||
// we don't own the simulation, but maybe we should...
|
||||
if (_outgoingPriority != NO_PRORITY) {
|
||||
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;
|
||||
return false;
|
||||
}
|
||||
|
@ -456,7 +460,10 @@ void EntityMotionState::sendUpdate(OctreeEditPacketSender* packetSender, const Q
|
|||
properties.setVelocity(_serverVelocity);
|
||||
properties.setAcceleration(_serverAcceleration);
|
||||
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
|
||||
quint64 now = usecTimestampNow();
|
||||
|
@ -526,7 +533,7 @@ void EntityMotionState::clearIncomingDirtyFlags() {
|
|||
}
|
||||
}
|
||||
|
||||
// virtual
|
||||
// virtual
|
||||
quint8 EntityMotionState::getSimulationPriority() const {
|
||||
if (_entity) {
|
||||
return _entity->getSimulationPriority();
|
||||
|
|
|
@ -130,6 +130,7 @@ bool ObjectActionOffset::updateArguments(QVariantMap arguments) {
|
|||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
activateBody();
|
||||
|
|
|
@ -163,6 +163,7 @@ bool ObjectActionSpring::updateArguments(QVariantMap arguments) {
|
|||
auto ownerEntity = _ownerEntity.lock();
|
||||
if (ownerEntity) {
|
||||
ownerEntity->setActionDataDirty(true);
|
||||
ownerEntity->setActionDataNeedsTransmit(true);
|
||||
}
|
||||
});
|
||||
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) {
|
||||
if (!_meshGroupsKnown && isLoaded()) {
|
||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges, bool showCollisionHull) {
|
||||
|
||||
if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) {
|
||||
_showCollisionHull = showCollisionHull;
|
||||
segregateMeshGroups();
|
||||
}
|
||||
|
||||
|
@ -525,8 +527,12 @@ bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChan
|
|||
return somethingAdded;
|
||||
}
|
||||
|
||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges, render::Item::Status::Getters& statusGetters) {
|
||||
if (!_meshGroupsKnown && isLoaded()) {
|
||||
bool Model::addToScene(std::shared_ptr<render::Scene> scene,
|
||||
render::PendingChanges& pendingChanges,
|
||||
render::Item::Status::Getters& statusGetters,
|
||||
bool showCollisionHull) {
|
||||
if ((!_meshGroupsKnown || showCollisionHull != _showCollisionHull) && isLoaded()) {
|
||||
_showCollisionHull = showCollisionHull;
|
||||
segregateMeshGroups();
|
||||
}
|
||||
|
||||
|
@ -1139,8 +1145,14 @@ AABox Model::getPartBounds(int meshIndex, int partIndex) {
|
|||
}
|
||||
|
||||
void Model::segregateMeshGroups() {
|
||||
const FBXGeometry& geometry = _geometry->getFBXGeometry();
|
||||
const std::vector<std::unique_ptr<NetworkMesh>>& networkMeshes = _geometry->getMeshes();
|
||||
QSharedPointer<NetworkGeometry> networkGeometry;
|
||||
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);
|
||||
|
||||
|
|
|
@ -76,10 +76,13 @@ public:
|
|||
return !_needsReload && isRenderable() && isActive() && isLoaded();
|
||||
}
|
||||
bool initWhenReady(render::ScenePointer scene);
|
||||
bool addToScene(std::shared_ptr<render::Scene> scene, render::PendingChanges& pendingChanges);
|
||||
bool addToScene(std::shared_ptr<render::Scene> scene,
|
||||
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 renderSetup(RenderArgs* args);
|
||||
bool isRenderable() const { return !_meshStates.isEmpty() || (isActive() && _geometry->getMeshes().empty()); }
|
||||
|
@ -368,6 +371,7 @@ private:
|
|||
bool _readyWhenAdded = false;
|
||||
bool _needsReload = true;
|
||||
bool _needsUpdateClusterMatrices = true;
|
||||
bool _showCollisionHull = false;
|
||||
|
||||
friend class MeshPartPayload;
|
||||
protected:
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
#include "RenderDeferredTask.h"
|
||||
|
||||
#include <PerfStat.h>
|
||||
#include <PathUtils.h>
|
||||
#include <RenderArgs.h>
|
||||
#include <ViewFrustum.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 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);
|
||||
_drawStatusJobIndex = _jobs.size() - 1;
|
||||
|
@ -387,4 +391,4 @@ void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const
|
|||
|
||||
});
|
||||
args->_batch = nullptr;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -97,7 +97,12 @@ public:
|
|||
int _drawStatusJobIndex = -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; } }
|
||||
|
||||
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) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemBounds_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemBounds_frag)));
|
||||
|
@ -56,18 +56,20 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemBoundsPipeline() {
|
|||
return _drawItemBoundsPipeline;
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() {
|
||||
const gpu::PipelinePointer DrawStatus::getDrawItemStatusPipeline() {
|
||||
if (!_drawItemStatusPipeline) {
|
||||
auto vs = gpu::ShaderPointer(gpu::Shader::createVertex(std::string(drawItemStatus_vert)));
|
||||
auto ps = gpu::ShaderPointer(gpu::Shader::createPixel(std::string(drawItemStatus_frag)));
|
||||
gpu::ShaderPointer program = gpu::ShaderPointer(gpu::Shader::createProgram(vs, ps));
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding(std::string("iconStatusMap"), 0));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
_drawItemStatusPosLoc = program->getUniforms().findLocation("inBoundPos");
|
||||
_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>();
|
||||
|
||||
|
@ -84,11 +86,23 @@ const gpu::PipelinePointer& DrawStatus::getDrawItemStatusPipeline() {
|
|||
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->_viewFrustum);
|
||||
RenderArgs* args = renderContext->args;
|
||||
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
|
||||
int nbItems = 0;
|
||||
|
@ -101,7 +115,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
|||
}
|
||||
|
||||
_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());
|
||||
glm::ivec4* itemStatus = reinterpret_cast<glm::ivec4*> (_itemStatus->editData());
|
||||
for (auto& item : inItems) {
|
||||
|
@ -112,11 +126,31 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
|||
(*itemAABox).setBox(item.bounds.getCorner(), 0.1f);
|
||||
}
|
||||
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++;
|
||||
itemAABox++;
|
||||
itemStatus++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -131,6 +165,7 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
|||
Transform viewMat;
|
||||
args->_viewFrustum->evalProjectionMatrix(projMat);
|
||||
args->_viewFrustum->evalViewTransform(viewMat);
|
||||
batch.setViewportTransform(args->_viewport);
|
||||
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
|
@ -144,20 +179,28 @@ void DrawStatus::run(const SceneContextPointer& sceneContext, const RenderContex
|
|||
|
||||
const unsigned int VEC3_ADRESS_OFFSET = 3;
|
||||
|
||||
for (int i = 0; i < nbItems; i++) {
|
||||
batch._glUniform3fv(_drawItemBoundPosLoc, 1, (const float*) (itemAABox + i));
|
||||
batch._glUniform3fv(_drawItemBoundDimLoc, 1, ((const float*) (itemAABox + i)) + VEC3_ADRESS_OFFSET);
|
||||
if ((renderContext->_drawItemStatus & showDisplayStatusFlag) > 0) {
|
||||
for (int i = 0; i < nbItems; i++) {
|
||||
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());
|
||||
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 _drawItemStatusPosLoc = -1;
|
||||
int _drawItemStatusDimLoc = -1;
|
||||
int _drawItemStatusValueLoc = -1;
|
||||
int _drawItemStatusValue0Loc = -1;
|
||||
int _drawItemStatusValue1Loc = -1;
|
||||
|
||||
gpu::Stream::FormatPointer _drawItemFormat;
|
||||
gpu::PipelinePointer _drawItemBoundsPipeline;
|
||||
gpu::PipelinePointer _drawItemStatusPipeline;
|
||||
gpu::BufferPointer _itemBounds;
|
||||
gpu::BufferPointer _itemStatus;
|
||||
gpu::TexturePointer _statusIconMap;
|
||||
|
||||
public:
|
||||
|
||||
DrawStatus() {}
|
||||
DrawStatus(const gpu::TexturePointer statusIconMap) { setStatusIconMap(statusIconMap); }
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemIDsBounds& inItems);
|
||||
|
||||
typedef Job::ModelI<DrawStatus, ItemIDsBounds> JobModel;
|
||||
|
||||
const gpu::PipelinePointer& getDrawItemBoundsPipeline();
|
||||
const gpu::PipelinePointer& getDrawItemStatusPipeline();
|
||||
const gpu::PipelinePointer getDrawItemBoundsPipeline();
|
||||
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; }
|
||||
|
||||
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) {}
|
||||
|
||||
void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) {
|
||||
|
|
|
@ -25,6 +25,10 @@ public:
|
|||
};
|
||||
typedef std::shared_ptr<SceneContext> SceneContextPointer;
|
||||
|
||||
// see examples/utilities/tools/renderEngineDebug.js
|
||||
const int showDisplayStatusFlag = 1;
|
||||
const int showNetworkStatusFlag = 2;
|
||||
|
||||
|
||||
class RenderContext {
|
||||
public:
|
||||
|
@ -49,7 +53,7 @@ public:
|
|||
int _numDrawnOverlay3DItems = 0;
|
||||
int _maxDrawnOverlay3DItems = -1;
|
||||
|
||||
bool _drawItemStatus = false;
|
||||
int _drawItemStatus = 0;
|
||||
bool _drawHitEffect = false;
|
||||
|
||||
bool _occlusionStatus = false;
|
||||
|
|
|
@ -72,17 +72,20 @@ void Item::Status::Value::setScale(float scale) {
|
|||
void Item::Status::Value::setColor(float hue) {
|
||||
// Convert the HUe from range [0, 360] to signed normalized value
|
||||
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 {
|
||||
for (unsigned int i = 0; i < (unsigned int)values.length(); i++) {
|
||||
if (i < _values.size()) {
|
||||
values[i] = _values[i]().getPackedData();
|
||||
} else {
|
||||
values[i] = Value::INVALID.getPackedData();
|
||||
}
|
||||
Item::Status::Values Item::Status::getCurrentValues() const {
|
||||
Values currentValues(_values.size());
|
||||
auto currentValue = currentValues.begin();
|
||||
for (auto& getter : _values) {
|
||||
(*currentValue) = getter();
|
||||
currentValue++;
|
||||
}
|
||||
return currentValues;
|
||||
}
|
||||
|
||||
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) {
|
||||
_resetItems.push_back(id);
|
||||
_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
|
||||
class Value {
|
||||
unsigned short _scale = 0xFFFF;
|
||||
unsigned short _color = 0xFFFF;
|
||||
unsigned char _color = 0xFF;
|
||||
unsigned char _icon = 0xFF;
|
||||
public:
|
||||
const static Value INVALID; // Invalid value meanss the status won't show
|
||||
|
||||
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]
|
||||
void setScale(float scale);
|
||||
// the color hue in the range [0, 360] representing the color wheel 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
|
||||
static const float RED; // 0.0f;
|
||||
|
@ -237,7 +241,10 @@ public:
|
|||
|
||||
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;
|
||||
|
||||
|
@ -301,7 +308,6 @@ public:
|
|||
|
||||
// Access the status
|
||||
const StatusPointer& getStatus() const { return _payload->getStatus(); }
|
||||
glm::ivec4 getStatusPackedValues() const;
|
||||
|
||||
protected:
|
||||
PayloadPointer _payload;
|
||||
|
|
|
@ -12,9 +12,20 @@
|
|||
//
|
||||
|
||||
in vec4 varColor;
|
||||
in vec3 varTexcoord;
|
||||
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) {
|
||||
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()$>
|
||||
|
||||
out vec4 varColor;
|
||||
out vec3 varTexcoord;
|
||||
|
||||
uniform vec3 inBoundPos;
|
||||
uniform vec3 inBoundDim;
|
||||
uniform ivec4 inStatus;
|
||||
uniform ivec4 inStatus0;
|
||||
uniform ivec4 inStatus1;
|
||||
|
||||
vec3 paintRainbow(float normalizedHue) {
|
||||
float v = normalizedHue * 6.f;
|
||||
|
@ -43,16 +45,28 @@ vec3 paintRainbow(float normalizedHue) {
|
|||
}
|
||||
}
|
||||
|
||||
vec2 unpackStatus(int v) {
|
||||
return vec2(clamp(float(int((v >> 0) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0),
|
||||
clamp(float(int((v >> 16) & 0xFFFF) - 32727) / 32727.0, -1.0, 1.0));
|
||||
const int INVALID_STATUS = int(0xFFFFFFFF);
|
||||
const int MAX_NUM_ICONS = 8;
|
||||
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) {
|
||||
const vec2 ICON_PIXEL_SIZE = vec2(10, 10);
|
||||
const vec2 MARGIN_PIXEL_SIZE = vec2(2, 2);
|
||||
const int NUM_VERTICES = 6;
|
||||
const vec4 UNIT_QUAD[NUM_VERTICES] = vec4[NUM_VERTICES](
|
||||
const int NUM_VERTICES_PER_ICON = 6;
|
||||
const vec4 UNIT_QUAD[NUM_VERTICES_PER_ICON] = vec4[NUM_VERTICES_PER_ICON](
|
||||
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)
|
||||
);
|
||||
|
||||
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
|
||||
vec4 anchorPoint = vec4(inBoundPos, 1.0) + vec4(inBoundDim, 0.0) * vec4(0.5, 0.5, 0.5, 0.0);
|
||||
TransformCamera cam = getTransformCamera();
|
||||
|
@ -68,36 +93,43 @@ void main(void) {
|
|||
<$transformModelToClipPos(cam, obj, anchorPoint, anchorPoint)$>
|
||||
|
||||
// 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 (inStatus[iconNum] == 0xFFFFFFFF) {
|
||||
if (packedIconStatus == INVALID_STATUS) {
|
||||
gl_Position = anchorPoint;
|
||||
varColor = vec4(1.0);
|
||||
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
|
||||
vec2 iconStatus = unpackStatus(inStatus[iconNum]);
|
||||
vec3 iconStatus = unpackStatus(packedIconStatus);
|
||||
|
||||
// Use the status for showing a color
|
||||
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
|
||||
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
|
||||
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
|
||||
int twoTriID = gl_VertexID - iconNum * NUM_VERTICES;
|
||||
vec4 pos = UNIT_QUAD[twoTriID];
|
||||
vec2 quadPixelPos = offset.xy + pos.xy * 0.5 * iconScale;
|
||||
vec2 quadPixelPos = offset.xy + quadPos.xy * 0.5 * iconScale;
|
||||
|
||||
vec4 viewport;
|
||||
<$transformCameraViewport(cam, viewport)$>;
|
||||
vec2 pixelToClip = vec2(2.0 / viewport.z, 2.0 / viewport.w);
|
||||
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 int getEngineMaxDrawnOverlay3DItems() { return _maxDrawnOverlay3DItems; }
|
||||
|
||||
Q_INVOKABLE void setEngineDisplayItemStatus(bool display) { _drawItemStatus = display; }
|
||||
Q_INVOKABLE bool doEngineDisplayItemStatus() { return _drawItemStatus; }
|
||||
Q_INVOKABLE void setEngineDisplayItemStatus(int display) { _drawItemStatus = display; }
|
||||
Q_INVOKABLE int doEngineDisplayItemStatus() { return _drawItemStatus; }
|
||||
|
||||
Q_INVOKABLE void setEngineDisplayHitEffect(bool display) { _drawHitEffect = display; }
|
||||
Q_INVOKABLE bool doEngineDisplayHitEffect() { return _drawHitEffect; }
|
||||
|
@ -143,7 +143,7 @@ protected:
|
|||
int _maxDrawnTransparentItems = -1;
|
||||
int _maxDrawnOverlay3DItems = -1;
|
||||
|
||||
bool _drawItemStatus = false;
|
||||
int _drawItemStatus = 0;
|
||||
|
||||
bool _drawHitEffect = false;
|
||||
|
||||
|
|
|
@ -68,17 +68,16 @@ public:
|
|||
class RenderArgs {
|
||||
public:
|
||||
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 RenderSide { MONO, STEREO_LEFT, STEREO_RIGHT };
|
||||
|
||||
enum DebugFlags {
|
||||
RENDER_DEBUG_NONE = 0,
|
||||
RENDER_DEBUG_HULLS = 1,
|
||||
RENDER_DEBUG_SIMULATION_OWNERSHIP = 2,
|
||||
RENDER_DEBUG_HULLS = 1
|
||||
};
|
||||
|
||||
|
||||
RenderArgs(std::shared_ptr<gpu::Context> context = nullptr,
|
||||
OctreeRenderer* renderer = nullptr,
|
||||
ViewFrustum* viewFrustum = nullptr,
|
||||
|
|
Loading…
Reference in a new issue