mirror of
https://github.com/overte-org/overte.git
synced 2025-08-13 13:40:19 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into depthReticleWork
This commit is contained in:
commit
8117d51324
30 changed files with 611 additions and 350 deletions
|
@ -564,7 +564,7 @@ function MyController(hand) {
|
|||
"additiveBlending": 0,
|
||||
"textures": "https://hifi-content.s3.amazonaws.com/alan/dev/textures/grabsprite-3.png"
|
||||
}
|
||||
|
||||
|
||||
this.particleBeamObject = Entities.addEntity(particleBeamPropertiesObject);
|
||||
};
|
||||
|
||||
|
@ -1588,7 +1588,9 @@ function MyController(hand) {
|
|||
|
||||
ids.forEach(function(id) {
|
||||
var props = Entities.getEntityProperties(id, ["boundingBox", "name"]);
|
||||
if (props.name === 'pointer') {
|
||||
if (!props ||
|
||||
!props.boundingBox ||
|
||||
props.name === 'pointer') {
|
||||
return;
|
||||
}
|
||||
var entityMinPoint = props.boundingBox.brn;
|
||||
|
|
|
@ -38,6 +38,10 @@ var lightOverlayManager = new LightOverlayManager();
|
|||
var cameraManager = new CameraManager();
|
||||
|
||||
var grid = Grid();
|
||||
gridTool = GridTool({
|
||||
horizontalGrid: grid
|
||||
});
|
||||
gridTool.setVisible(false);
|
||||
|
||||
var entityListTool = EntityListTool();
|
||||
|
||||
|
@ -341,7 +345,7 @@ var toolBar = (function() {
|
|||
isActive = active;
|
||||
if (!isActive) {
|
||||
entityListTool.setVisible(false);
|
||||
// gridTool.setVisible(false);
|
||||
gridTool.setVisible(false);
|
||||
grid.setEnabled(false);
|
||||
propertiesTool.setVisible(false);
|
||||
selectionManager.clearSelections();
|
||||
|
@ -349,7 +353,7 @@ var toolBar = (function() {
|
|||
} else {
|
||||
hasShownPropertiesTool = false;
|
||||
entityListTool.setVisible(true);
|
||||
// gridTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
Window.setFocus();
|
||||
|
|
|
@ -33,8 +33,8 @@
|
|||
elPosY.value = origin.y.toFixed(2);
|
||||
}
|
||||
|
||||
if (data.minorGridWidth !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridWidth;
|
||||
if (data.minorGridEvery !== undefined) {
|
||||
elMinorSpacing.value = data.minorGridEvery;
|
||||
}
|
||||
|
||||
if (data.majorGridEvery !== undefined) {
|
||||
|
@ -60,7 +60,7 @@
|
|||
origin: {
|
||||
y: elPosY.value,
|
||||
},
|
||||
minorGridWidth: elMinorSpacing.value,
|
||||
minorGridEvery: elMinorSpacing.value,
|
||||
majorGridEvery: elMajorSpacing.value,
|
||||
gridColor: gridColor,
|
||||
colorIndex: gridColorIndex,
|
||||
|
@ -132,21 +132,21 @@
|
|||
<div id="horizontal-position" class="property-section">
|
||||
<label>Position (Y Axis)</label>
|
||||
<span>
|
||||
<input type='number' id="horiz-y" class="number" value="0.0" step="0.1"></input>
|
||||
<input type='number' id="horiz-y" class="number" step="0.1"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Minor Grid Size</label>
|
||||
<span>
|
||||
<input type='number' id="minor-spacing" min="0" step="0.01", ></input>
|
||||
<input type='number' id="minor-spacing" min="0.2" step="0.2"></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div class="property-section">
|
||||
<label>Major Grid Every</label>
|
||||
<span>
|
||||
<input type='number' id="major-spacing" min="2" step="1", ></input>
|
||||
<input type='number' id="major-spacing" min="1" step="1", ></input>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -12,24 +12,26 @@ Grid = function(opts) {
|
|||
];
|
||||
var colorIndex = 0;
|
||||
var gridAlpha = 0.6;
|
||||
var origin = { x: 0, y: 0, z: 0 };
|
||||
var origin = { x: 0, y: +MyAvatar.getJointPosition('LeftToeBase').y.toFixed(1) + 0.1, z: 0 };
|
||||
var scale = 500;
|
||||
var minorGridEvery = 1.0;
|
||||
var majorGridEvery = 5;
|
||||
var minorGridWidth = 0.2;
|
||||
var halfSize = 40;
|
||||
var yOffset = 0.001;
|
||||
|
||||
var worldSize = 16384;
|
||||
|
||||
var snapToGrid = false;
|
||||
|
||||
var gridOverlay = Overlays.addOverlay("grid", {
|
||||
position: { x: 0 , y: 0, z: 0 },
|
||||
visible: true,
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
dimensions: { x: scale, y: scale, z: scale },
|
||||
position: origin,
|
||||
visible: false,
|
||||
drawInFront: false,
|
||||
color: colors[0],
|
||||
alpha: gridAlpha,
|
||||
rotation: Quat.fromPitchYawRollDegrees(90, 0, 0),
|
||||
minorGridWidth: 0.1,
|
||||
majorGridEvery: 2,
|
||||
minorGridEvery: minorGridEvery,
|
||||
majorGridEvery: majorGridEvery,
|
||||
});
|
||||
|
||||
that.visible = false;
|
||||
|
@ -39,17 +41,13 @@ Grid = function(opts) {
|
|||
return origin;
|
||||
}
|
||||
|
||||
that.getMinorIncrement = function() { return minorGridWidth; };
|
||||
that.getMajorIncrement = function() { return minorGridWidth * majorGridEvery; };
|
||||
|
||||
that.getMinorGridWidth = function() { return minorGridWidth; };
|
||||
that.setMinorGridWidth = function(value) {
|
||||
minorGridWidth = value;
|
||||
that.getMinorIncrement = function() { return minorGridEvery; };
|
||||
that.setMinorIncrement = function(value) {
|
||||
minorGridEvery = value;
|
||||
updateGrid();
|
||||
};
|
||||
|
||||
that.getMajorGridEvery = function() { return majorGridEvery; };
|
||||
that.setMajorGridEvery = function(value) {
|
||||
}
|
||||
that.getMajorIncrement = function() { return majorGridEvery; };
|
||||
that.setMajorIncrement = function(value) {
|
||||
majorGridEvery = value;
|
||||
updateGrid();
|
||||
};
|
||||
|
@ -106,7 +104,7 @@ Grid = function(opts) {
|
|||
dimensions = { x: 0, y: 0, z: 0 };
|
||||
}
|
||||
|
||||
var spacing = majorOnly ? (minorGridWidth * majorGridEvery) : minorGridWidth;
|
||||
var spacing = majorOnly ? majorGridEvery : minorGridEvery;
|
||||
|
||||
position = Vec3.subtract(position, origin);
|
||||
|
||||
|
@ -122,7 +120,7 @@ Grid = function(opts) {
|
|||
return delta;
|
||||
}
|
||||
|
||||
var spacing = majorOnly ? (minorGridWidth * majorGridEvery) : minorGridWidth;
|
||||
var spacing = majorOnly ? majorGridEvery : minorGridEvery;
|
||||
|
||||
var snappedDelta = {
|
||||
x: Math.round(delta.x / spacing) * spacing,
|
||||
|
@ -135,9 +133,7 @@ Grid = function(opts) {
|
|||
|
||||
|
||||
that.setPosition = function(newPosition, noUpdate) {
|
||||
origin = Vec3.subtract(newPosition, { x: 0, y: yOffset, z: 0 });
|
||||
origin.x = 0;
|
||||
origin.z = 0;
|
||||
origin = { x: 0, y: newPosition.y, z: 0 };
|
||||
updateGrid();
|
||||
|
||||
if (!noUpdate) {
|
||||
|
@ -149,7 +145,7 @@ Grid = function(opts) {
|
|||
if (that.onUpdate) {
|
||||
that.onUpdate({
|
||||
origin: origin,
|
||||
minorGridWidth: minorGridWidth,
|
||||
minorGridEvery: minorGridEvery,
|
||||
majorGridEvery: majorGridEvery,
|
||||
gridSize: halfSize,
|
||||
visible: that.visible,
|
||||
|
@ -171,8 +167,8 @@ Grid = function(opts) {
|
|||
that.setPosition(pos, true);
|
||||
}
|
||||
|
||||
if (data.minorGridWidth) {
|
||||
minorGridWidth = data.minorGridWidth;
|
||||
if (data.minorGridEvery) {
|
||||
minorGridEvery = data.minorGridEvery;
|
||||
}
|
||||
|
||||
if (data.majorGridEvery) {
|
||||
|
@ -191,20 +187,22 @@ Grid = function(opts) {
|
|||
that.setVisible(data.visible, true);
|
||||
}
|
||||
|
||||
updateGrid();
|
||||
updateGrid(true);
|
||||
}
|
||||
|
||||
function updateGrid() {
|
||||
function updateGrid(noUpdate) {
|
||||
Overlays.editOverlay(gridOverlay, {
|
||||
position: { x: origin.y, y: origin.y, z: -origin.y },
|
||||
position: { x: 0, y: origin.y, z: 0 },
|
||||
visible: that.visible && that.enabled,
|
||||
minorGridWidth: minorGridWidth,
|
||||
minorGridEvery: minorGridEvery,
|
||||
majorGridEvery: majorGridEvery,
|
||||
color: colors[colorIndex],
|
||||
alpha: gridAlpha,
|
||||
});
|
||||
|
||||
that.emitUpdate();
|
||||
if (!noUpdate) {
|
||||
that.emitUpdate();
|
||||
}
|
||||
}
|
||||
|
||||
function cleanup() {
|
||||
|
@ -247,7 +245,7 @@ GridTool = function(opts) {
|
|||
} else if (data.type == "update") {
|
||||
horizontalGrid.update(data);
|
||||
for (var i = 0; i < listeners.length; i++) {
|
||||
listeners[i](data);
|
||||
listeners[i] && listeners[i](data);
|
||||
}
|
||||
} else if (data.type == "action") {
|
||||
var action = data.action;
|
||||
|
|
|
@ -10,12 +10,19 @@ import "../js/Utils.js" as Utils
|
|||
// windows will be childed.
|
||||
FocusScope {
|
||||
id: desktop
|
||||
anchors.fill: parent;
|
||||
objectName: "desktop"
|
||||
|
||||
// Allow the scale of the desktop to be changed without screwing up the size relative to the parent.
|
||||
height: parent.height / scale
|
||||
width: parent.width / scale
|
||||
|
||||
onHeightChanged: d.repositionAll();
|
||||
onWidthChanged: d.repositionAll();
|
||||
|
||||
// Controls and windows can trigger this signal to ensure the desktop becomes visible
|
||||
// when they're opened.
|
||||
signal showDesktop();
|
||||
|
||||
// Allows QML/JS to find the desktop through the parent chain
|
||||
property bool desktopRoot: true
|
||||
|
||||
|
@ -217,6 +224,8 @@ FocusScope {
|
|||
}
|
||||
|
||||
reposition(targetWindow);
|
||||
|
||||
showDesktop();
|
||||
}
|
||||
|
||||
function reposition(item) {
|
||||
|
@ -315,7 +324,7 @@ FocusScope {
|
|||
enabled: DebugQML
|
||||
onTriggered: focusDebugger.visible = !focusDebugger.visible
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -1198,7 +1198,8 @@ void Application::initializeUi() {
|
|||
// OffscreenUi is a subclass of OffscreenQmlSurface specifically designed to
|
||||
// support the window management and scripting proxies for VR use
|
||||
offscreenUi->createDesktop(QString("hifi/Desktop.qml"));
|
||||
|
||||
connect(offscreenUi.data(), &OffscreenUi::showDesktop, this, &Application::showDesktop);
|
||||
|
||||
// FIXME either expose so that dialogs can set this themselves or
|
||||
// do better detection in the offscreen UI of what has focus
|
||||
offscreenUi->setNavigationFocused(false);
|
||||
|
@ -5130,3 +5131,9 @@ void Application::readArgumentsFromLocalSocket() {
|
|||
qApp->openUrl(QString::fromUtf8(message));
|
||||
}
|
||||
}
|
||||
|
||||
void Application::showDesktop() {
|
||||
if (!_overlayConductor.getEnabled()) {
|
||||
_overlayConductor.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -280,6 +280,7 @@ public slots:
|
|||
void runTests();
|
||||
|
||||
private slots:
|
||||
void showDesktop();
|
||||
void clearDomainOctreeDetails();
|
||||
void idle(uint64_t now);
|
||||
void aboutToQuit();
|
||||
|
|
|
@ -117,8 +117,8 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) {
|
|||
static const glm::vec4 inputColor = { 0.3f, 1.0f, 0.3f, 1.0f };
|
||||
static const glm::vec4 outputLeftColor = { 1.0f, 0.3f, 0.3f, 1.0f };
|
||||
static const glm::vec4 outputRightColor = { 0.3f, 0.3f, 1.0f, 1.0f };
|
||||
static const int gridRows = 2;
|
||||
int gridCols = _framesPerScope;
|
||||
static const int gridCols = 2;
|
||||
int gridRows = _framesPerScope;
|
||||
|
||||
int x = (width - (int)SCOPE_WIDTH) / 2;
|
||||
int y = (height - (int)SCOPE_HEIGHT) / 2;
|
||||
|
@ -127,6 +127,12 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) {
|
|||
|
||||
gpu::Batch& batch = *renderArgs->_batch;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
// Grid uses its own pipeline, so draw it before setting another
|
||||
const float GRID_EDGE = 0.005f;
|
||||
geometryCache->renderGrid(batch, glm::vec2(x, y), glm::vec2(x + w, y + h),
|
||||
gridRows, gridCols, GRID_EDGE, gridColor, true, _audioScopeGrid);
|
||||
|
||||
geometryCache->useSimpleDrawPipeline(batch);
|
||||
auto textureCache = DependencyManager::get<TextureCache>();
|
||||
batch.setResourceTexture(0, textureCache->getWhiteTexture());
|
||||
|
@ -139,7 +145,6 @@ void AudioScope::render(RenderArgs* renderArgs, int width, int height) {
|
|||
batch.setViewTransform(Transform());
|
||||
|
||||
geometryCache->renderQuad(batch, x, y, w, h, backgroundColor, _audioScopeBackground);
|
||||
geometryCache->renderGrid(batch, x, y, w, h, gridRows, gridCols, gridColor, _audioScopeGrid);
|
||||
renderLineStrip(batch, _inputID, inputColor, x, y, _samplesPerScope, _scopeInputOffset, _scopeInput);
|
||||
renderLineStrip(batch, _outputLeftID, outputLeftColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputLeft);
|
||||
renderLineStrip(batch, _outputRightD, outputRightColor, x, y, _samplesPerScope, _scopeOutputOffset, _scopeOutputRight);
|
||||
|
|
|
@ -13,6 +13,8 @@
|
|||
|
||||
#include <QScriptValue>
|
||||
|
||||
#include <OctreeConstants.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -20,17 +22,28 @@
|
|||
|
||||
|
||||
QString const Grid3DOverlay::TYPE = "grid";
|
||||
const float DEFAULT_SCALE = 100.0f;
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay() :
|
||||
_minorGridWidth(1.0),
|
||||
_majorGridEvery(5) {
|
||||
Grid3DOverlay::Grid3DOverlay() {
|
||||
setDimensions(DEFAULT_SCALE);
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) :
|
||||
Planar3DOverlay(grid3DOverlay),
|
||||
_minorGridWidth(grid3DOverlay->_minorGridWidth),
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery)
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery),
|
||||
_minorGridEvery(grid3DOverlay->_minorGridEvery)
|
||||
{
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
AABox Grid3DOverlay::getBounds() const {
|
||||
if (_followCamera) {
|
||||
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
||||
const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE);
|
||||
return DOMAIN_BOX;
|
||||
}
|
||||
return Planar3DOverlay::getBounds();
|
||||
}
|
||||
|
||||
void Grid3DOverlay::render(RenderArgs* args) {
|
||||
|
@ -38,15 +51,8 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
const int MINOR_GRID_DIVISIONS = 200;
|
||||
const int MAJOR_GRID_DIVISIONS = 100;
|
||||
const float MAX_COLOR = 255.0f;
|
||||
|
||||
// center the grid around the camera position on the plane
|
||||
glm::vec3 rotated = glm::inverse(getRotation()) * args->_viewFrustum->getPosition();
|
||||
|
||||
float spacing = _minorGridWidth;
|
||||
|
||||
float alpha = getAlpha();
|
||||
xColor color = getColor();
|
||||
glm::vec4 gridColor(color.red / MAX_COLOR, color.green / MAX_COLOR, color.blue / MAX_COLOR, alpha);
|
||||
|
@ -54,72 +60,65 @@ void Grid3DOverlay::render(RenderArgs* args) {
|
|||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
auto minCorner = glm::vec2(-0.5f, -0.5f);
|
||||
auto maxCorner = glm::vec2(0.5f, 0.5f);
|
||||
|
||||
auto position = getPosition();
|
||||
if (_followCamera) {
|
||||
// Get the camera position rounded to the nearest major grid line
|
||||
// This grid is for UI and should lie on worldlines
|
||||
auto cameraPosition =
|
||||
(float)_majorGridEvery * glm::round(args->_viewFrustum->getPosition() / (float)_majorGridEvery);
|
||||
|
||||
position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
|
||||
}
|
||||
|
||||
Transform transform;
|
||||
transform.setRotation(getRotation());
|
||||
transform.setScale(glm::vec3(getDimensions(), 1.0f));
|
||||
transform.setTranslation(position);
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
|
||||
// Minor grid
|
||||
{
|
||||
auto position = glm::vec3(_minorGridWidth * (floorf(rotated.x / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MINOR_GRID_DIVISIONS / 2),
|
||||
getPosition().z);
|
||||
float scale = MINOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
transform.setScale(scale);
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, MINOR_GRID_DIVISIONS, MINOR_GRID_DIVISIONS, gridColor);
|
||||
}
|
||||
|
||||
// Major grid
|
||||
{
|
||||
spacing *= _majorGridEvery;
|
||||
auto position = glm::vec3(spacing * (floorf(rotated.x / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
spacing * (floorf(rotated.y / spacing) - MAJOR_GRID_DIVISIONS / 2),
|
||||
getPosition().z);
|
||||
float scale = MAJOR_GRID_DIVISIONS * spacing;
|
||||
|
||||
transform.setTranslation(position);
|
||||
transform.setScale(scale);
|
||||
|
||||
// FIXME: THe line width of 4.0f is not supported anymore, we ll need a workaround
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, MAJOR_GRID_DIVISIONS, MAJOR_GRID_DIVISIONS, gridColor);
|
||||
}
|
||||
const float MINOR_GRID_EDGE = 0.0025f;
|
||||
const float MAJOR_GRID_EDGE = 0.005f;
|
||||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
|
||||
_minorGridRowDivisions, _minorGridColDivisions, MINOR_GRID_EDGE,
|
||||
_majorGridRowDivisions, _majorGridColDivisions, MAJOR_GRID_EDGE,
|
||||
gridColor, _drawInFront);
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (getAlpha() != 1.0f) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
return render::ShapeKey::Builder().withOwnPipeline();
|
||||
}
|
||||
|
||||
void Grid3DOverlay::setProperties(const QScriptValue& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
|
||||
if (properties.property("minorGridWidth").isValid()) {
|
||||
_minorGridWidth = properties.property("minorGridWidth").toVariant().toFloat();
|
||||
if (properties.property("followCamera").isValid()) {
|
||||
_followCamera = properties.property("followCamera").toVariant().toBool();
|
||||
}
|
||||
|
||||
if (properties.property("majorGridEvery").isValid()) {
|
||||
_majorGridEvery = properties.property("majorGridEvery").toVariant().toInt();
|
||||
}
|
||||
|
||||
if (properties.property("minorGridEvery").isValid()) {
|
||||
_minorGridEvery = properties.property("minorGridEvery").toVariant().toFloat();
|
||||
}
|
||||
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
QScriptValue Grid3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "minorGridWidth") {
|
||||
return _minorGridWidth;
|
||||
if (property == "followCamera") {
|
||||
return _followCamera;
|
||||
}
|
||||
if (property == "majorGridEvery") {
|
||||
return _majorGridEvery;
|
||||
}
|
||||
if (property == "minorGridEvery") {
|
||||
return _minorGridEvery;
|
||||
}
|
||||
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
@ -128,3 +127,16 @@ Grid3DOverlay* Grid3DOverlay::createClone() const {
|
|||
return new Grid3DOverlay(this);
|
||||
}
|
||||
|
||||
void Grid3DOverlay::updateGrid() {
|
||||
const int MAJOR_GRID_EVERY_MIN = 1;
|
||||
const float MINOR_GRID_EVERY_MIN = 0.01f;
|
||||
|
||||
_majorGridEvery = std::max(_majorGridEvery, MAJOR_GRID_EVERY_MIN);
|
||||
_minorGridEvery = std::max(_minorGridEvery, MINOR_GRID_EVERY_MIN);
|
||||
|
||||
_majorGridRowDivisions = getDimensions().x / _majorGridEvery;
|
||||
_majorGridColDivisions = getDimensions().y / _majorGridEvery;
|
||||
|
||||
_minorGridRowDivisions = getDimensions().x / _minorGridEvery;
|
||||
_minorGridColDivisions = getDimensions().y / _minorGridEvery;
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ public:
|
|||
Grid3DOverlay();
|
||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
virtual void render(RenderArgs* args);
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
virtual void setProperties(const QScriptValue& properties);
|
||||
|
@ -31,9 +33,21 @@ public:
|
|||
|
||||
virtual Grid3DOverlay* createClone() const;
|
||||
|
||||
// Grids are UI tools, and may not be intersected (pickable)
|
||||
virtual bool findRayIntersection(const glm::vec3&, const glm::vec3&, float&, BoxFace&, glm::vec3&) { return false; }
|
||||
|
||||
private:
|
||||
float _minorGridWidth;
|
||||
int _majorGridEvery;
|
||||
void updateGrid();
|
||||
|
||||
bool _followCamera { true };
|
||||
|
||||
int _majorGridEvery { 5 };
|
||||
float _majorGridRowDivisions;
|
||||
float _majorGridColDivisions;
|
||||
|
||||
float _minorGridEvery { 1.0f };
|
||||
float _minorGridRowDivisions;
|
||||
float _minorGridColDivisions;
|
||||
};
|
||||
|
||||
#endif // hifi_Grid3DOverlay_h
|
||||
|
|
|
@ -20,7 +20,7 @@ public:
|
|||
Planar3DOverlay();
|
||||
Planar3DOverlay(const Planar3DOverlay* planar3DOverlay);
|
||||
|
||||
AABox getBounds() const;
|
||||
virtual AABox getBounds() const;
|
||||
|
||||
glm::vec2 getDimensions() const { return _dimensions; }
|
||||
void setDimensions(float value) { _dimensions = glm::vec2(value); }
|
||||
|
|
|
@ -260,10 +260,22 @@ QNetworkReply* OBJReader::request(QUrl& url, bool isTest) {
|
|||
QNetworkAccessManager& networkAccessManager = NetworkAccessManager::getInstance();
|
||||
QNetworkRequest netRequest(url);
|
||||
QNetworkReply* netReply = isTest ? networkAccessManager.head(netRequest) : networkAccessManager.get(netRequest);
|
||||
if (!qApp) {
|
||||
return netReply;
|
||||
}
|
||||
QEventLoop loop; // Create an event loop that will quit when we get the finished signal
|
||||
QObject::connect(netReply, SIGNAL(finished()), &loop, SLOT(quit()));
|
||||
loop.exec(); // Nothing is going to happen on this whole run thread until we get this
|
||||
netReply->waitForReadyRead(-1); // so we might as well block this thread waiting for the response, rather than
|
||||
|
||||
bool aboutToQuit { false };
|
||||
auto connection = QObject::connect(qApp, &QCoreApplication::aboutToQuit, [&] {
|
||||
aboutToQuit = true;
|
||||
});
|
||||
static const int WAIT_TIMEOUT_MS = 500;
|
||||
while (qApp && !aboutToQuit && !netReply->isReadable()) {
|
||||
netReply->waitForReadyRead(WAIT_TIMEOUT_MS); // so we might as well block this thread waiting for the response, rather than
|
||||
}
|
||||
QObject::disconnect(connection);
|
||||
return netReply; // trying to sync later on.
|
||||
}
|
||||
|
||||
|
|
|
@ -315,6 +315,8 @@ OffscreenQmlSurface::OffscreenQmlSurface() {
|
|||
}
|
||||
|
||||
OffscreenQmlSurface::~OffscreenQmlSurface() {
|
||||
QObject::disconnect(&_updateTimer);
|
||||
QObject::disconnect(qApp);
|
||||
_renderer->stop();
|
||||
delete _rootItem;
|
||||
delete _renderer;
|
||||
|
@ -322,6 +324,10 @@ OffscreenQmlSurface::~OffscreenQmlSurface() {
|
|||
delete _qmlEngine;
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::onAboutToQuit() {
|
||||
QObject::disconnect(&_updateTimer);
|
||||
}
|
||||
|
||||
void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
||||
_renderer = new OffscreenQmlRenderer(this, shareContext);
|
||||
_renderer->_renderControl->_renderWindow = _proxyWindow;
|
||||
|
@ -334,12 +340,9 @@ void OffscreenQmlSurface::create(QOpenGLContext* shareContext) {
|
|||
// When Quick says there is a need to render, we will not render immediately. Instead,
|
||||
// a timer with a small interval is used to get better performance.
|
||||
_updateTimer.setInterval(MIN_TIMER_MS);
|
||||
connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
|
||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit, [this]{
|
||||
disconnect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
|
||||
});
|
||||
QObject::connect(&_updateTimer, &QTimer::timeout, this, &OffscreenQmlSurface::updateQuick);
|
||||
QObject::connect(qApp, &QCoreApplication::aboutToQuit, this, &OffscreenQmlSurface::onAboutToQuit);
|
||||
_updateTimer.start();
|
||||
|
||||
_qmlComponent = new QQmlComponent(_qmlEngine);
|
||||
_qmlEngine->rootContext()->setContextProperty("offscreenWindow", QVariant::fromValue(getWindow()));
|
||||
}
|
||||
|
|
|
@ -74,6 +74,7 @@ signals:
|
|||
public slots:
|
||||
void requestUpdate();
|
||||
void requestRender();
|
||||
void onAboutToQuit();
|
||||
|
||||
private:
|
||||
QObject* finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f);
|
||||
|
|
47
libraries/gpu/src/gpu/Paint.slh
Normal file
47
libraries/gpu/src/gpu/Paint.slh
Normal file
|
@ -0,0 +1,47 @@
|
|||
<!
|
||||
// Paint.slh
|
||||
// libraries/gpu/src
|
||||
//
|
||||
// Created by Zach Pomerantz on 2/19/2016.
|
||||
// Copyright 2016 High Fidelity, Inc.
|
||||
//
|
||||
// Fragment shader utility functions. Will fail compilation in vertex shaders.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
!>
|
||||
<@if not GPU_PAINT_SLH@>
|
||||
<@def GPU_PAINT_SLH@>
|
||||
|
||||
float paintStripe(float value, float offset, float scale, float edge) {
|
||||
float width = fwidth(value);
|
||||
float normalizedWidth = width * scale;
|
||||
|
||||
float x0 = (value + offset) * scale - normalizedWidth / 2;
|
||||
float x1 = x0 + normalizedWidth;
|
||||
|
||||
float balance = 1.0 - edge;
|
||||
float i0 = edge * floor(x0) + max(0.0, fract(x0) - balance);
|
||||
float i1 = edge * floor(x1) + max(0.0, fract(x1) - balance);
|
||||
float strip = (i1 - i0) / normalizedWidth;
|
||||
|
||||
return clamp(strip, 0.0, 1.0);
|
||||
}
|
||||
|
||||
float paintGrid(vec2 value, vec2 offset, vec2 scale, vec2 edge) {
|
||||
return max(
|
||||
paintStripe(value.x, offset.x, scale.x, edge.x),
|
||||
paintStripe(value.y, offset.y, scale.y, edge.y));
|
||||
}
|
||||
|
||||
float paintGridMajor(vec2 value, vec2 offset, vec2 scale, vec2 edge) {
|
||||
return paintGrid(value, offset, scale, edge);
|
||||
}
|
||||
|
||||
float paintGridMajorMinor(vec2 value, vec4 offset, vec4 scale, vec4 edge) {
|
||||
return max(
|
||||
paintGrid(value, offset.xy, scale.xy, edge.xy),
|
||||
paintGrid(value, offset.zw, scale.zw, edge.zw));
|
||||
}
|
||||
|
||||
<@endif@>
|
|
@ -21,6 +21,17 @@
|
|||
class NLPacket : public udt::Packet {
|
||||
Q_OBJECT
|
||||
public:
|
||||
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Packet Type | Packet Version |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Node UUID | Hash (only if verified) | Optional (only if sourced)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// NLPacket Header Format
|
||||
|
||||
// this is used by the Octree classes - must be known at compile time
|
||||
static const int MAX_PACKET_HEADER_SIZE =
|
||||
sizeof(udt::Packet::SequenceNumberAndBitField) + sizeof(udt::Packet::MessageNumberAndBitField) +
|
||||
|
|
|
@ -26,10 +26,65 @@ namespace udt {
|
|||
static const int UDP_SEND_BUFFER_SIZE_BYTES = 1048576;
|
||||
static const int UDP_RECEIVE_BUFFER_SIZE_BYTES = 1048576;
|
||||
static const int DEFAULT_SYN_INTERVAL_USECS = 10 * 1000;
|
||||
static const int SEQUENCE_NUMBER_BITS = sizeof(SequenceNumber) * 8;
|
||||
static const int MESSAGE_LINE_NUMBER_BITS = 32;
|
||||
static const int MESSAGE_NUMBER_BITS = 30;
|
||||
static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 1);
|
||||
|
||||
|
||||
// Header constants
|
||||
|
||||
// Bit sizes (in order)
|
||||
static const int CONTROL_BIT_SIZE = 1;
|
||||
static const int RELIABILITY_BIT_SIZE = 1;
|
||||
static const int MESSAGE_BIT_SIZE = 1;
|
||||
static const int OBFUSCATION_LEVEL_SIZE = 2;
|
||||
static const int SEQUENCE_NUMBER_SIZE= 27;
|
||||
|
||||
static const int PACKET_POSITION_SIZE = 2;
|
||||
static const int MESSAGE_NUMBER_SIZE = 30;
|
||||
|
||||
static const int MESSAGE_PART_NUMBER_SIZE = 32;
|
||||
|
||||
// Offsets
|
||||
static const int SEQUENCE_NUMBER_OFFSET = 0;
|
||||
static const int OBFUSCATION_LEVEL_OFFSET = SEQUENCE_NUMBER_OFFSET + SEQUENCE_NUMBER_SIZE;
|
||||
static const int MESSAGE_BIT_OFFSET = OBFUSCATION_LEVEL_OFFSET + OBFUSCATION_LEVEL_SIZE;
|
||||
static const int RELIABILITY_BIT_OFFSET = MESSAGE_BIT_OFFSET + MESSAGE_BIT_SIZE;
|
||||
static const int CONTROL_BIT_OFFSET = RELIABILITY_BIT_OFFSET + RELIABILITY_BIT_SIZE;
|
||||
|
||||
static const int MESSAGE_NUMBER_OFFSET = 0;
|
||||
static const int PACKET_POSITION_OFFSET = MESSAGE_NUMBER_OFFSET + MESSAGE_NUMBER_SIZE;
|
||||
|
||||
static const int MESSAGE_PART_NUMBER_OFFSET = 0;
|
||||
|
||||
// Masks
|
||||
static const uint32_t CONTROL_BIT_MASK = uint32_t(1) << CONTROL_BIT_OFFSET;
|
||||
static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << RELIABILITY_BIT_OFFSET;
|
||||
static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << MESSAGE_BIT_OFFSET;
|
||||
static const uint32_t OBFUSCATION_LEVEL_MASK = uint32_t(3) << OBFUSCATION_LEVEL_OFFSET;
|
||||
static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK | OBFUSCATION_LEVEL_MASK;
|
||||
static const uint32_t SEQUENCE_NUMBER_MASK = ~BIT_FIELD_MASK;
|
||||
|
||||
static const uint32_t PACKET_POSITION_MASK = uint32_t(3) << PACKET_POSITION_OFFSET;
|
||||
static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK;
|
||||
|
||||
static const uint32_t MESSAGE_PART_NUMBER_MASK = ~uint32_t(0);
|
||||
|
||||
|
||||
// Static checks
|
||||
static_assert(CONTROL_BIT_SIZE + RELIABILITY_BIT_SIZE + MESSAGE_BIT_SIZE +
|
||||
OBFUSCATION_LEVEL_SIZE + SEQUENCE_NUMBER_SIZE == 32, "Sequence number line size incorrect");
|
||||
static_assert(PACKET_POSITION_SIZE + MESSAGE_NUMBER_SIZE == 32, "Message number line size incorrect");
|
||||
static_assert(MESSAGE_PART_NUMBER_SIZE == 32, "Message part number line size incorrect");
|
||||
|
||||
static_assert(CONTROL_BIT_MASK == 0x80000000, "CONTROL_BIT_MASK incorrect");
|
||||
static_assert(RELIABILITY_BIT_MASK == 0x40000000, "RELIABILITY_BIT_MASK incorrect");
|
||||
static_assert(MESSAGE_BIT_MASK == 0x20000000, "MESSAGE_BIT_MASK incorrect");
|
||||
static_assert(OBFUSCATION_LEVEL_MASK == 0x18000000, "OBFUSCATION_LEVEL_MASK incorrect");
|
||||
static_assert(BIT_FIELD_MASK == 0xF8000000, "BIT_FIELD_MASK incorrect");
|
||||
static_assert(SEQUENCE_NUMBER_MASK == 0x07FFFFFF, "SEQUENCE_NUMBER_MASK incorrect");
|
||||
|
||||
static_assert(PACKET_POSITION_MASK == 0xC0000000, "PACKET_POSITION_MASK incorrect");
|
||||
static_assert(MESSAGE_NUMBER_MASK == 0x3FFFFFFF, "MESSAGE_NUMBER_MASK incorrect");
|
||||
|
||||
static_assert(MESSAGE_PART_NUMBER_MASK == 0xFFFFFFFF, "MESSAGE_PART_NUMBER_MASK incorrect");
|
||||
}
|
||||
|
||||
#endif // hifi_udt_Constants_h
|
||||
|
|
|
@ -11,10 +11,35 @@
|
|||
|
||||
#include "Packet.h"
|
||||
|
||||
#include <array>
|
||||
|
||||
#include <LogHandler.h>
|
||||
|
||||
using namespace udt;
|
||||
|
||||
static int packetMetaTypeId = qRegisterMetaType<Packet*>("Packet*");
|
||||
|
||||
using Key = uint64_t;
|
||||
static const std::array<Key, 4> KEYS {{
|
||||
0x0,
|
||||
0x6362726973736574,
|
||||
0x7362697261726461,
|
||||
0x72687566666d616e,
|
||||
}};
|
||||
|
||||
void xorHelper(char* start, int size, Key key) {
|
||||
const auto end = start + size;
|
||||
|
||||
auto p = start;
|
||||
for (; p + sizeof(Key) < end; p += sizeof(Key)) {
|
||||
*reinterpret_cast<Key*>(p) ^= key;
|
||||
}
|
||||
|
||||
for (int i = 0; p < end; ++p || ++i) {
|
||||
*p ^= *(reinterpret_cast<const char*>(&key) + i);
|
||||
}
|
||||
}
|
||||
|
||||
int Packet::localHeaderSize(bool isPartOfMessage) {
|
||||
return sizeof(Packet::SequenceNumberAndBitField) +
|
||||
(isPartOfMessage ? sizeof(Packet::MessageNumberAndBitField) + sizeof(MessagePartNumber) : 0);
|
||||
|
@ -69,44 +94,48 @@ Packet::Packet(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& se
|
|||
readHeader();
|
||||
|
||||
adjustPayloadStartAndCapacity(Packet::localHeaderSize(_isPartOfMessage), _payloadSize > 0);
|
||||
|
||||
if (getObfuscationLevel() != Packet::NoObfuscation) {
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
QString debugString = "Unobfuscating packet %1 with level %2";
|
||||
debugString = debugString.arg(QString::number((uint32_t)getSequenceNumber()),
|
||||
QString::number(getObfuscationLevel()));
|
||||
|
||||
if (isPartOfMessage()) {
|
||||
debugString += "\n";
|
||||
debugString += " Message Number: %1, Part Number: %2.";
|
||||
debugString = debugString.arg(QString::number(getMessageNumber()),
|
||||
QString::number(getMessagePartNumber()));
|
||||
}
|
||||
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Unobfuscating packet .*");
|
||||
qDebug() << qPrintable(debugString);
|
||||
#endif
|
||||
|
||||
obfuscate(NoObfuscation); // Undo obfuscation
|
||||
}
|
||||
}
|
||||
|
||||
Packet::Packet(const Packet& other) :
|
||||
BasePacket(other)
|
||||
{
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
Packet::Packet(const Packet& other) : BasePacket(other) {
|
||||
copyMembers(other);
|
||||
}
|
||||
|
||||
Packet& Packet::operator=(const Packet& other) {
|
||||
BasePacket::operator=(other);
|
||||
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
|
||||
copyMembers(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
Packet::Packet(Packet&& other) :
|
||||
BasePacket(std::move(other))
|
||||
{
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
Packet::Packet(Packet&& other) : BasePacket(std::move(other)) {
|
||||
copyMembers(other);
|
||||
}
|
||||
|
||||
Packet& Packet::operator=(Packet&& other) {
|
||||
BasePacket::operator=(std::move(other));
|
||||
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
|
||||
copyMembers(other);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
@ -124,13 +153,27 @@ void Packet::writeSequenceNumber(SequenceNumber sequenceNumber) const {
|
|||
writeHeader();
|
||||
}
|
||||
|
||||
static const uint32_t RELIABILITY_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 2);
|
||||
static const uint32_t MESSAGE_BIT_MASK = uint32_t(1) << (SEQUENCE_NUMBER_BITS - 3);
|
||||
static const uint32_t BIT_FIELD_MASK = CONTROL_BIT_MASK | RELIABILITY_BIT_MASK | MESSAGE_BIT_MASK;
|
||||
void Packet::obfuscate(ObfuscationLevel level) {
|
||||
auto obfuscationKey = KEYS[getObfuscationLevel()] ^ KEYS[level]; // Undo old and apply new one.
|
||||
if (obfuscationKey != 0) {
|
||||
xorHelper(getData() + localHeaderSize(isPartOfMessage()),
|
||||
getDataSize() - localHeaderSize(isPartOfMessage()), obfuscationKey);
|
||||
|
||||
static const uint8_t PACKET_POSITION_OFFSET = 30;
|
||||
static const uint32_t PACKET_POSITION_MASK = uint32_t(0x03) << PACKET_POSITION_OFFSET;
|
||||
static const uint32_t MESSAGE_NUMBER_MASK = ~PACKET_POSITION_MASK;
|
||||
// Update members and header
|
||||
_obfuscationLevel = level;
|
||||
writeHeader();
|
||||
}
|
||||
}
|
||||
|
||||
void Packet::copyMembers(const Packet& other) {
|
||||
_isReliable = other._isReliable;
|
||||
_isPartOfMessage = other._isPartOfMessage;
|
||||
_obfuscationLevel = other._obfuscationLevel;
|
||||
_sequenceNumber = other._sequenceNumber;
|
||||
_packetPosition = other._packetPosition;
|
||||
_messageNumber = other._messageNumber;
|
||||
_messagePartNumber = other._messagePartNumber;
|
||||
}
|
||||
|
||||
void Packet::readHeader() const {
|
||||
SequenceNumberAndBitField* seqNumBitField = reinterpret_cast<SequenceNumberAndBitField*>(_packet.get());
|
||||
|
@ -139,10 +182,12 @@ void Packet::readHeader() const {
|
|||
|
||||
_isReliable = (bool) (*seqNumBitField & RELIABILITY_BIT_MASK); // Only keep reliability bit
|
||||
_isPartOfMessage = (bool) (*seqNumBitField & MESSAGE_BIT_MASK); // Only keep message bit
|
||||
_sequenceNumber = SequenceNumber{ *seqNumBitField & ~BIT_FIELD_MASK }; // Remove the bit field
|
||||
_obfuscationLevel = (ObfuscationLevel)((*seqNumBitField & OBFUSCATION_LEVEL_MASK) >> OBFUSCATION_LEVEL_OFFSET);
|
||||
_sequenceNumber = SequenceNumber{ *seqNumBitField & SEQUENCE_NUMBER_MASK }; // Remove the bit field
|
||||
|
||||
if (_isPartOfMessage) {
|
||||
MessageNumberAndBitField* messageNumberAndBitField = seqNumBitField + 1;
|
||||
|
||||
_messageNumber = *messageNumberAndBitField & MESSAGE_NUMBER_MASK;
|
||||
_packetPosition = static_cast<PacketPosition>(*messageNumberAndBitField >> PACKET_POSITION_OFFSET);
|
||||
|
||||
|
@ -163,6 +208,10 @@ void Packet::writeHeader() const {
|
|||
if (_isReliable) {
|
||||
*seqNumBitField |= RELIABILITY_BIT_MASK;
|
||||
}
|
||||
|
||||
if (_obfuscationLevel != NoObfuscation) {
|
||||
*seqNumBitField |= (_obfuscationLevel << OBFUSCATION_LEVEL_OFFSET);
|
||||
}
|
||||
|
||||
if (_isPartOfMessage) {
|
||||
*seqNumBitField |= MESSAGE_BIT_MASK;
|
||||
|
|
|
@ -25,6 +25,25 @@ namespace udt {
|
|||
class Packet : public BasePacket {
|
||||
Q_OBJECT
|
||||
public:
|
||||
// Packet Header Format
|
||||
//
|
||||
// 0 1 2 3
|
||||
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// |C|R|M| O | Sequence Number |
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | P | Message Number | Optional (only if M = 1)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
// | Message Part Number | Optional (only if M = 1)
|
||||
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||
//
|
||||
// C: Control bit
|
||||
// R: Reliable bit
|
||||
// M: Message bit
|
||||
// O: Obfuscation level
|
||||
// P: Position bits
|
||||
|
||||
|
||||
// NOTE: The SequenceNumber is only actually 29 bits to leave room for a bit field
|
||||
using SequenceNumberAndBitField = uint32_t;
|
||||
|
||||
|
@ -35,12 +54,20 @@ public:
|
|||
|
||||
// Use same size as MessageNumberAndBitField so we can use the enum with bitwise operations
|
||||
enum PacketPosition : MessageNumberAndBitField {
|
||||
ONLY = 0x0,
|
||||
FIRST = 0x2,
|
||||
MIDDLE = 0x3,
|
||||
LAST = 0x1
|
||||
ONLY = 0x0, // 00
|
||||
FIRST = 0x2, // 10
|
||||
MIDDLE = 0x3, // 11
|
||||
LAST = 0x1 // 01
|
||||
};
|
||||
|
||||
|
||||
// Use same size as SequenceNumberAndBitField so we can use the enum with bitwise operations
|
||||
enum ObfuscationLevel : SequenceNumberAndBitField {
|
||||
NoObfuscation = 0x0, // 00
|
||||
ObfuscationL1 = 0x1, // 01
|
||||
ObfuscationL2 = 0x2, // 10
|
||||
ObfuscationL3 = 0x3, // 11
|
||||
};
|
||||
|
||||
static std::unique_ptr<Packet> create(qint64 size = -1, bool isReliable = false, bool isPartOfMessage = false);
|
||||
static std::unique_ptr<Packet> fromReceivedPacket(std::unique_ptr<char[]> data, qint64 size, const HifiSockAddr& senderSockAddr);
|
||||
|
||||
|
@ -56,7 +83,8 @@ public:
|
|||
|
||||
bool isPartOfMessage() const { return _isPartOfMessage; }
|
||||
bool isReliable() const { return _isReliable; }
|
||||
|
||||
|
||||
ObfuscationLevel getObfuscationLevel() const { return _obfuscationLevel; }
|
||||
SequenceNumber getSequenceNumber() const { return _sequenceNumber; }
|
||||
MessageNumber getMessageNumber() const { return _messageNumber; }
|
||||
PacketPosition getPacketPosition() const { return _packetPosition; }
|
||||
|
@ -64,6 +92,7 @@ public:
|
|||
|
||||
void writeMessageNumber(MessageNumber messageNumber, PacketPosition position, MessagePartNumber messagePartNumber);
|
||||
void writeSequenceNumber(SequenceNumber sequenceNumber) const;
|
||||
void obfuscate(ObfuscationLevel level);
|
||||
|
||||
protected:
|
||||
Packet(qint64 size, bool isReliable = false, bool isPartOfMessage = false);
|
||||
|
@ -76,6 +105,8 @@ protected:
|
|||
Packet& operator=(Packet&& other);
|
||||
|
||||
private:
|
||||
void copyMembers(const Packet& other);
|
||||
|
||||
// Header readers - these read data to member variables after pulling packet off wire
|
||||
void readHeader() const;
|
||||
void writeHeader() const;
|
||||
|
@ -83,6 +114,7 @@ private:
|
|||
// Simple holders to prevent multiple reading and bitwise ops
|
||||
mutable bool _isReliable { false };
|
||||
mutable bool _isPartOfMessage { false };
|
||||
mutable ObfuscationLevel _obfuscationLevel { NoObfuscation };
|
||||
mutable SequenceNumber _sequenceNumber { 0 };
|
||||
mutable MessageNumber _messageNumber { 0 };
|
||||
mutable PacketPosition _packetPosition { PacketPosition::ONLY };
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
using namespace udt;
|
||||
|
||||
MessageNumber PacketQueue::getNextMessageNumber() {
|
||||
static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_BITS;
|
||||
static const MessageNumber MAX_MESSAGE_NUMBER = MessageNumber(1) << MESSAGE_NUMBER_SIZE;
|
||||
_currentMessageNumber = (_currentMessageNumber + 1) % MAX_MESSAGE_NUMBER;
|
||||
return _currentMessageNumber;
|
||||
}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include <QtCore/QDateTime>
|
||||
#include <QtCore/QThread>
|
||||
|
||||
#include <LogHandler.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
#include "../NetworkLogging.h"
|
||||
|
@ -225,7 +226,9 @@ void SendQueue::sendNewPacketAndAddToSentList(std::unique_ptr<Packet> newPacket,
|
|||
{
|
||||
// Insert the packet we have just sent in the sent list
|
||||
QWriteLocker locker(&_sentLock);
|
||||
_sentPackets[newPacket->getSequenceNumber()].swap(newPacket);
|
||||
auto& entry = _sentPackets[newPacket->getSequenceNumber()];
|
||||
entry.first = 0; // No resend
|
||||
entry.second.swap(newPacket);
|
||||
}
|
||||
Q_ASSERT_X(!newPacket, "SendQueue::sendNewPacketAndAddToSentList()", "Overriden packet in sent list");
|
||||
|
||||
|
@ -354,14 +357,46 @@ bool SendQueue::maybeResendPacket() {
|
|||
auto it = _sentPackets.find(resendNumber);
|
||||
|
||||
if (it != _sentPackets.end()) {
|
||||
auto& entry = it->second;
|
||||
// we found the packet - grab it
|
||||
auto& resendPacket = *(it->second);
|
||||
|
||||
// send it off
|
||||
sendPacket(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
auto& resendPacket = *(entry.second);
|
||||
++entry.first; // Add 1 resend
|
||||
|
||||
Packet::ObfuscationLevel level = (Packet::ObfuscationLevel)(entry.first < 2 ? 0 : (entry.first - 2) % 4);
|
||||
|
||||
if (level != Packet::NoObfuscation) {
|
||||
#ifdef UDT_CONNECTION_DEBUG
|
||||
QString debugString = "Obfuscating packet %1 with level %2";
|
||||
debugString = debugString.arg(QString::number((uint32_t)resendPacket.getSequenceNumber()),
|
||||
QString::number(level));
|
||||
if (resendPacket.isPartOfMessage()) {
|
||||
debugString += "\n";
|
||||
debugString += " Message Number: %1, Part Number: %2.";
|
||||
debugString = debugString.arg(QString::number(resendPacket.getMessageNumber()),
|
||||
QString::number(resendPacket.getMessagePartNumber()));
|
||||
}
|
||||
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex("^Obfuscating packet .*");
|
||||
qCritical() << qPrintable(debugString);
|
||||
#endif
|
||||
|
||||
// Create copy of the packet
|
||||
auto packet = Packet::createCopy(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
|
||||
// Obfuscate packet
|
||||
packet->obfuscate(level);
|
||||
|
||||
// send it off
|
||||
sendPacket(*packet);
|
||||
} else {
|
||||
// send it off
|
||||
sendPacket(resendPacket);
|
||||
|
||||
// unlock the sent packets
|
||||
sentLocker.unlock();
|
||||
}
|
||||
|
||||
emit packetRetransmitted();
|
||||
|
||||
|
|
|
@ -126,7 +126,8 @@ private:
|
|||
LossList _naks; // Sequence numbers of packets to resend
|
||||
|
||||
mutable QReadWriteLock _sentLock; // Protects the sent packet list
|
||||
std::unordered_map<SequenceNumber, std::unique_ptr<Packet>> _sentPackets; // Packets waiting for ACK.
|
||||
using PacketResendPair = std::pair<uint8_t, std::unique_ptr<Packet>>; // Number of resend + packet ptr
|
||||
std::unordered_map<SequenceNumber, PacketResendPair> _sentPackets; // Packets waiting for ACK.
|
||||
|
||||
std::mutex _handshakeMutex; // Protects the handshake ACK condition_variable
|
||||
std::atomic<bool> _hasReceivedHandshakeACK { false }; // flag for receipt of handshake ACK from client
|
||||
|
|
|
@ -24,9 +24,9 @@ public:
|
|||
using Type = int32_t;
|
||||
using UType = uint32_t;
|
||||
|
||||
// Values are for 29 bit SequenceNumber
|
||||
static const Type THRESHOLD = 0x0FFFFFFF; // threshold for comparing sequence numbers
|
||||
static const Type MAX = 0x1FFFFFFF; // maximum sequence number used in UDT
|
||||
// Values are for 27 bit SequenceNumber
|
||||
static const Type THRESHOLD = 0x03FFFFFF; // threshold for comparing sequence numbers
|
||||
static const Type MAX = 0x07FFFFFF; // maximum sequence number used in UDT
|
||||
|
||||
SequenceNumber() = default;
|
||||
SequenceNumber(const SequenceNumber& other) : _value(other._value) {}
|
||||
|
|
|
@ -277,7 +277,7 @@ void Socket::readPendingDatagrams() {
|
|||
if (packet->isReliable()) {
|
||||
// if this was a reliable packet then signal the matching connection with the sequence number
|
||||
auto& connection = findOrCreateConnection(senderSockAddr);
|
||||
|
||||
|
||||
if (!connection.processReceivedSequenceNumber(packet->getSequenceNumber(),
|
||||
packet->getDataSize(),
|
||||
packet->getPayloadSize())) {
|
||||
|
|
|
@ -22,17 +22,19 @@
|
|||
#include "TextureCache.h"
|
||||
#include "RenderUtilsLogging.h"
|
||||
|
||||
#include "standardTransformPNTC_vert.h"
|
||||
#include "standardDrawTexture_frag.h"
|
||||
|
||||
#include "gpu/StandardShaderLib.h"
|
||||
|
||||
#include "model/TextureMap.h"
|
||||
|
||||
#include "standardTransformPNTC_vert.h"
|
||||
#include "standardDrawTexture_frag.h"
|
||||
|
||||
#include "simple_vert.h"
|
||||
#include "simple_textured_frag.h"
|
||||
#include "simple_textured_emisive_frag.h"
|
||||
|
||||
#include "grid_frag.h"
|
||||
|
||||
//#define WANT_DEBUG
|
||||
|
||||
const int GeometryCache::UNKNOWN_ID = -1;
|
||||
|
@ -564,186 +566,49 @@ void GeometryCache::renderWireSphere(gpu::Batch& batch) {
|
|||
renderWireShape(batch, Sphere);
|
||||
}
|
||||
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
int majorRows, int majorCols, float majorEdge,
|
||||
int minorRows, int minorCols, float minorEdge,
|
||||
const glm::vec4& color, bool isLayered, int id) {
|
||||
static const glm::vec2 MIN_TEX_COORD(0.0f, 0.0f);
|
||||
static const glm::vec2 MAX_TEX_COORD(1.0f, 1.0f);
|
||||
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
|
||||
IntPair key(xDivisions, yDivisions);
|
||||
Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));
|
||||
|
||||
int vertices = (xDivisions + 1 + yDivisions + 1) * 2;
|
||||
if (!_gridBuffers.contains(key)) {
|
||||
auto verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
|
||||
float* vertexData = new float[vertices * 2];
|
||||
float* vertex = vertexData;
|
||||
|
||||
for (int i = 0; i <= xDivisions; i++) {
|
||||
float x = (float)i / xDivisions;
|
||||
|
||||
*(vertex++) = x;
|
||||
*(vertex++) = 0.0f;
|
||||
|
||||
*(vertex++) = x;
|
||||
*(vertex++) = 1.0f;
|
||||
}
|
||||
for (int i = 0; i <= yDivisions; i++) {
|
||||
float y = (float)i / yDivisions;
|
||||
|
||||
*(vertex++) = 0.0f;
|
||||
*(vertex++) = y;
|
||||
|
||||
*(vertex++) = 1.0f;
|
||||
*(vertex++) = y;
|
||||
}
|
||||
|
||||
verticesBuffer->append(sizeof(float) * vertices * 2, (gpu::Byte*) vertexData);
|
||||
delete[] vertexData;
|
||||
|
||||
_gridBuffers[key] = verticesBuffer;
|
||||
}
|
||||
|
||||
if (!_gridColors.contains(colorKey)) {
|
||||
auto colorBuffer = std::make_shared<gpu::Buffer>();
|
||||
_gridColors[colorKey] = colorBuffer;
|
||||
|
||||
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||
((int(color.z * 255.0f) & 0xFF) << 16) |
|
||||
((int(color.w * 255.0f) & 0xFF) << 24);
|
||||
|
||||
int* colorData = new int[vertices];
|
||||
int* colorDataAt = colorData;
|
||||
|
||||
for(int v = 0; v < vertices; v++) {
|
||||
*(colorDataAt++) = compactColor;
|
||||
}
|
||||
|
||||
colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData);
|
||||
delete[] colorData;
|
||||
}
|
||||
gpu::BufferPointer verticesBuffer = _gridBuffers[key];
|
||||
gpu::BufferPointer colorBuffer = _gridColors[colorKey];
|
||||
|
||||
const int VERTICES_SLOT = 0;
|
||||
const int COLOR_SLOT = 1;
|
||||
auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||
|
||||
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
|
||||
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(VERTICES_SLOT, verticesView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colorView);
|
||||
batch.draw(gpu::LINES, vertices, 0);
|
||||
}
|
||||
|
||||
// TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that??
|
||||
void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) {
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(renderutils) << "GeometryCache::renderGrid(x["<<x<<"], "
|
||||
"y["<<y<<"],"
|
||||
"w["<<width<<"],"
|
||||
"h["<<height<<"],"
|
||||
"rows["<<rows<<"],"
|
||||
"cols["<<cols<<"],"
|
||||
" id:"<<id<<")...";
|
||||
#endif
|
||||
|
||||
bool registered = (id != UNKNOWN_ID);
|
||||
Vec3Pair key(glm::vec3(x, y, width), glm::vec3(height, rows, cols));
|
||||
Vec3Pair colorKey(glm::vec3(color.x, color.y, rows), glm::vec3(color.z, color.y, cols));
|
||||
Vec2FloatPair majorKey(glm::vec2(majorRows, majorCols), majorEdge);
|
||||
Vec2FloatPair minorKey(glm::vec2(minorRows, minorCols), minorEdge);
|
||||
Vec2FloatPairPair key(majorKey, minorKey);
|
||||
|
||||
int vertices = (cols + 1 + rows + 1) * 2;
|
||||
if ((registered && (!_registeredAlternateGridBuffers.contains(id) || _lastRegisteredAlternateGridBuffers[id] != key))
|
||||
|| (!registered && !_alternateGridBuffers.contains(key))) {
|
||||
// Make the gridbuffer
|
||||
if ((registered && (!_registeredGridBuffers.contains(id) || _lastRegisteredGridBuffer[id] != key)) ||
|
||||
(!registered && !_gridBuffers.contains(key))) {
|
||||
GridSchema gridSchema;
|
||||
GridBuffer gridBuffer = std::make_shared<gpu::Buffer>(sizeof(GridSchema), (const gpu::Byte*) &gridSchema);
|
||||
|
||||
if (registered && _registeredAlternateGridBuffers.contains(id)) {
|
||||
_registeredAlternateGridBuffers[id].reset();
|
||||
#ifdef WANT_DEBUG
|
||||
qCDebug(renderutils) << "renderGrid()... RELEASING REGISTERED VERTICES BUFFER";
|
||||
#endif
|
||||
if (registered && _registeredGridBuffers.contains(id)) {
|
||||
gridBuffer = _registeredGridBuffers[id];
|
||||
}
|
||||
|
||||
auto verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
if (registered) {
|
||||
_registeredAlternateGridBuffers[id] = verticesBuffer;
|
||||
_lastRegisteredAlternateGridBuffers[id] = key;
|
||||
_registeredGridBuffers[id] = gridBuffer;
|
||||
_lastRegisteredGridBuffer[id] = key;
|
||||
} else {
|
||||
_alternateGridBuffers[key] = verticesBuffer;
|
||||
_gridBuffers[key] = gridBuffer;
|
||||
}
|
||||
|
||||
float* vertexData = new float[vertices * 2];
|
||||
float* vertex = vertexData;
|
||||
|
||||
int dx = width / cols;
|
||||
int dy = height / rows;
|
||||
int tx = x;
|
||||
int ty = y;
|
||||
|
||||
// Draw horizontal grid lines
|
||||
for (int i = rows + 1; --i >= 0; ) {
|
||||
*(vertex++) = x;
|
||||
*(vertex++) = ty;
|
||||
|
||||
*(vertex++) = x + width;
|
||||
*(vertex++) = ty;
|
||||
|
||||
ty += dy;
|
||||
}
|
||||
// Draw vertical grid lines
|
||||
for (int i = cols + 1; --i >= 0; ) {
|
||||
*(vertex++) = tx;
|
||||
*(vertex++) = y;
|
||||
|
||||
*(vertex++) = tx;
|
||||
*(vertex++) = y + height;
|
||||
tx += dx;
|
||||
}
|
||||
|
||||
verticesBuffer->append(sizeof(float) * vertices * 2, (gpu::Byte*) vertexData);
|
||||
delete[] vertexData;
|
||||
gridBuffer.edit<GridSchema>().period = glm::vec4(majorRows, majorCols, minorRows, minorCols);
|
||||
gridBuffer.edit<GridSchema>().offset.x = -(majorEdge / majorRows) / 2;
|
||||
gridBuffer.edit<GridSchema>().offset.y = -(majorEdge / majorCols) / 2;
|
||||
gridBuffer.edit<GridSchema>().offset.z = -(minorEdge / minorRows) / 2;
|
||||
gridBuffer.edit<GridSchema>().offset.w = -(minorEdge / minorCols) / 2;
|
||||
gridBuffer.edit<GridSchema>().edge = glm::vec4(glm::vec2(majorEdge),
|
||||
// If rows or columns are not set, do not draw minor gridlines
|
||||
glm::vec2((minorRows != 0 && minorCols != 0) ? minorEdge : 0.0f));
|
||||
}
|
||||
|
||||
if (!_gridColors.contains(colorKey)) {
|
||||
auto colorBuffer = std::make_shared<gpu::Buffer>();
|
||||
_gridColors[colorKey] = colorBuffer;
|
||||
// Set the grid pipeline
|
||||
useGridPipeline(batch, registered ? _registeredGridBuffers[id] : _gridBuffers[key], isLayered);
|
||||
|
||||
int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
|
||||
((int(color.y * 255.0f) & 0xFF) << 8) |
|
||||
((int(color.z * 255.0f) & 0xFF) << 16) |
|
||||
((int(color.w * 255.0f) & 0xFF) << 24);
|
||||
|
||||
int* colorData = new int[vertices];
|
||||
int* colorDataAt = colorData;
|
||||
|
||||
|
||||
for(int v = 0; v < vertices; v++) {
|
||||
*(colorDataAt++) = compactColor;
|
||||
}
|
||||
|
||||
colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData);
|
||||
delete[] colorData;
|
||||
}
|
||||
gpu::BufferPointer verticesBuffer = registered ? _registeredAlternateGridBuffers[id] : _alternateGridBuffers[key];
|
||||
|
||||
gpu::BufferPointer colorBuffer = _gridColors[colorKey];
|
||||
|
||||
const int VERTICES_SLOT = 0;
|
||||
const int COLOR_SLOT = 1;
|
||||
auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
|
||||
|
||||
streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0);
|
||||
streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
|
||||
|
||||
gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element);
|
||||
gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element);
|
||||
|
||||
batch.setInputFormat(streamFormat);
|
||||
batch.setInputBuffer(VERTICES_SLOT, verticesView);
|
||||
batch.setInputBuffer(COLOR_SLOT, colorView);
|
||||
batch.draw(gpu::LINES, vertices, 0);
|
||||
renderQuad(batch, minCorner, maxCorner, MIN_TEX_COORD, MAX_TEX_COORD, color, id);
|
||||
}
|
||||
|
||||
void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) {
|
||||
|
@ -1772,7 +1637,6 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
|||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
|
||||
|
||||
// enable decal blend
|
||||
state->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
|
||||
|
@ -1792,6 +1656,30 @@ void GeometryCache::useSimpleDrawPipeline(gpu::Batch& batch, bool noBlend) {
|
|||
}
|
||||
}
|
||||
|
||||
void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool isLayered) {
|
||||
if (!_gridPipeline) {
|
||||
auto vs = gpu::Shader::createVertex(std::string(standardTransformPNTC_vert));
|
||||
auto ps = gpu::Shader::createPixel(std::string(grid_frag));
|
||||
auto program = gpu::Shader::createProgram(vs, ps);
|
||||
gpu::Shader::makeProgram((*program));
|
||||
_gridSlot = program->getBuffers().findLocation("gridBuffer");
|
||||
|
||||
auto stateLayered = std::make_shared<gpu::State>();
|
||||
stateLayered->setBlendFunction(true, gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA);
|
||||
_gridPipelineLayered = gpu::Pipeline::create(program, stateLayered);
|
||||
|
||||
auto state = std::make_shared<gpu::State>(stateLayered->getValues());
|
||||
const float DEPTH_BIAS = 0.001f;
|
||||
state->setDepthBias(DEPTH_BIAS);
|
||||
state->setDepthTest(true, false, gpu::LESS_EQUAL);
|
||||
_gridPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
|
||||
gpu::PipelinePointer pipeline = isLayered ? _gridPipelineLayered : _gridPipeline;
|
||||
batch.setPipeline(pipeline);
|
||||
batch.setUniformBuffer(_gridSlot, gridBuffer);
|
||||
}
|
||||
|
||||
|
||||
|
||||
class SimpleProgramKey {
|
||||
|
|
|
@ -31,8 +31,8 @@
|
|||
|
||||
class SimpleProgramKey;
|
||||
|
||||
typedef glm::vec3 Vec3Key;
|
||||
|
||||
typedef QPair<glm::vec2, float> Vec2FloatPair;
|
||||
typedef QPair<Vec2FloatPair, Vec2FloatPair> Vec2FloatPairPair;
|
||||
typedef QPair<glm::vec2, glm::vec2> Vec2Pair;
|
||||
typedef QPair<Vec2Pair, Vec2Pair> Vec2PairPair;
|
||||
typedef QPair<glm::vec3, glm::vec3> Vec3Pair;
|
||||
|
@ -43,9 +43,10 @@ typedef QPair<Vec3Pair, Vec4Pair> Vec3PairVec4Pair;
|
|||
typedef QPair<Vec4Pair, glm::vec4> Vec4PairVec4;
|
||||
typedef QPair<Vec4Pair, Vec4Pair> Vec4PairVec4Pair;
|
||||
|
||||
inline uint qHash(const glm::vec2& v, uint seed) {
|
||||
inline uint qHash(const Vec2FloatPairPair& v, uint seed) {
|
||||
// multiply by prime numbers greater than the possible size
|
||||
return qHash(v.x + 5009 * v.y, seed);
|
||||
return qHash(v.first.first.x + 5009 * v.first.first.y + 5011 * v.first.second +
|
||||
5021 * v.second.first.x + 5023 * v.second.first.y + 5039 * v.second.second);
|
||||
}
|
||||
|
||||
inline uint qHash(const Vec2Pair& v, uint seed) {
|
||||
|
@ -203,8 +204,14 @@ public:
|
|||
void renderWireSphere(gpu::Batch& batch);
|
||||
size_t getSphereTriangleCount();
|
||||
|
||||
void renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color);
|
||||
void renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
int majorRows, int majorCols, float majorEdge,
|
||||
int minorRows, int minorCols, float minorEdge,
|
||||
const glm::vec4& color, bool isLayered, int id = UNKNOWN_ID);
|
||||
void renderGrid(gpu::Batch& batch, const glm::vec2& minCorner, const glm::vec2& maxCorner,
|
||||
int rows, int cols, float edge, const glm::vec4& color, bool isLayered, int id = UNKNOWN_ID) {
|
||||
renderGrid(batch, minCorner, maxCorner, rows, cols, edge, 0, 0, 0.0f, color, isLayered, id);
|
||||
}
|
||||
|
||||
void renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id = UNKNOWN_ID);
|
||||
|
||||
|
@ -310,6 +317,19 @@ private:
|
|||
gpu::BufferPointer _shapeVertices{ std::make_shared<gpu::Buffer>() };
|
||||
gpu::BufferPointer _shapeIndices{ std::make_shared<gpu::Buffer>() };
|
||||
|
||||
class GridSchema {
|
||||
public:
|
||||
// data is arranged as majorRow, majorCol, minorRow, minorCol
|
||||
glm::vec4 period;
|
||||
glm::vec4 offset;
|
||||
glm::vec4 edge;
|
||||
};
|
||||
using GridBuffer = gpu::BufferView;
|
||||
void useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bool isLayered);
|
||||
gpu::PipelinePointer _gridPipeline;
|
||||
gpu::PipelinePointer _gridPipelineLayered;
|
||||
int _gridSlot;
|
||||
|
||||
class BatchItemDetails {
|
||||
public:
|
||||
static int population;
|
||||
|
@ -366,11 +386,9 @@ private:
|
|||
QHash<Vec3PairVec2Pair, BatchItemDetails> _dashedLines;
|
||||
QHash<int, BatchItemDetails> _registeredDashedLines;
|
||||
|
||||
QHash<IntPair, gpu::BufferPointer> _gridBuffers;
|
||||
QHash<Vec3Pair, gpu::BufferPointer> _alternateGridBuffers;
|
||||
QHash<int, gpu::BufferPointer> _registeredAlternateGridBuffers;
|
||||
QHash<int, Vec3Pair> _lastRegisteredAlternateGridBuffers;
|
||||
QHash<Vec3Pair, gpu::BufferPointer> _gridColors;
|
||||
QHash<int, Vec2FloatPairPair> _lastRegisteredGridBuffer;
|
||||
QHash<Vec2FloatPairPair, GridBuffer> _gridBuffers;
|
||||
QHash<int, GridBuffer> _registeredGridBuffers;
|
||||
|
||||
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
||||
|
||||
|
|
44
libraries/render-utils/src/grid.slf
Normal file
44
libraries/render-utils/src/grid.slf
Normal file
|
@ -0,0 +1,44 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
// grid.slf
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Zach Pomerantz on 2/16/2016.
|
||||
// Copyright 2016 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 gpu/Paint.slh@>
|
||||
|
||||
struct Grid {
|
||||
vec4 period;
|
||||
vec4 offset;
|
||||
vec4 edge;
|
||||
};
|
||||
|
||||
uniform gridBuffer { Grid grid; };
|
||||
Grid getGrid() { return grid; };
|
||||
|
||||
in vec2 varTexCoord0;
|
||||
in vec4 varColor;
|
||||
|
||||
out vec4 outFragColor;
|
||||
|
||||
void main(void) {
|
||||
Grid grid = getGrid();
|
||||
|
||||
float alpha;
|
||||
if (grid.edge.z == 0.0) {
|
||||
alpha = paintGrid(varTexCoord0, grid.offset.xy, grid.period.xy, grid.edge.xy);
|
||||
} else {
|
||||
alpha = paintGridMajorMinor(varTexCoord0, grid.offset, grid.period, grid.edge);
|
||||
}
|
||||
if (alpha == 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
outFragColor = vec4(varColor.xyz, varColor.w * alpha);
|
||||
}
|
|
@ -144,7 +144,12 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, const QString& fileNam
|
|||
ScriptEngine::~ScriptEngine() {
|
||||
qCDebug(scriptengine) << "Script Engine shutting down (destructor) for script:" << getFilename();
|
||||
|
||||
DependencyManager::get<ScriptEngines>()->removeScriptEngine(this);
|
||||
auto scriptEngines = DependencyManager::get<ScriptEngines>();
|
||||
if (scriptEngines) {
|
||||
scriptEngines->removeScriptEngine(this);
|
||||
} else {
|
||||
qCWarning(scriptengine) << "Script destroyed after ScriptEngines!";
|
||||
}
|
||||
}
|
||||
|
||||
void ScriptEngine::disconnectNonEssentialSignals() {
|
||||
|
|
|
@ -112,6 +112,7 @@ void OffscreenUi::create(QOpenGLContext* context) {
|
|||
}
|
||||
|
||||
void OffscreenUi::show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f) {
|
||||
emit showDesktop();
|
||||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
// First load?
|
||||
if (!item) {
|
||||
|
@ -127,6 +128,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<voi
|
|||
QQuickItem* item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
// Already loaded?
|
||||
if (item) {
|
||||
emit showDesktop();
|
||||
item->setVisible(!item->isVisible());
|
||||
return;
|
||||
}
|
||||
|
@ -134,6 +136,7 @@ void OffscreenUi::toggle(const QUrl& url, const QString& name, std::function<voi
|
|||
load(url, f);
|
||||
item = getRootItem()->findChild<QQuickItem*>(name);
|
||||
if (item && !item->isVisible()) {
|
||||
emit showDesktop();
|
||||
item->setVisible(true);
|
||||
}
|
||||
}
|
||||
|
@ -439,6 +442,8 @@ void OffscreenUi::createDesktop(const QUrl& url) {
|
|||
new VrMenu(this);
|
||||
|
||||
new KeyboardFocusHack();
|
||||
|
||||
connect(_desktop, SIGNAL(showDesktop()), this, SLOT(showDesktop()));
|
||||
}
|
||||
|
||||
QQuickItem* OffscreenUi::getDesktop() {
|
||||
|
|
|
@ -106,6 +106,9 @@ public:
|
|||
// Compatibility with QInputDialog::getItem
|
||||
static QString getItem(void *ignored, const QString & title, const QString & label, const QStringList & items, int current = 0, bool editable = true, bool * ok = 0, Qt::WindowFlags flags = 0, Qt::InputMethodHints inputMethodHints = Qt::ImhNone);
|
||||
|
||||
signals:
|
||||
void showDesktop();
|
||||
|
||||
private:
|
||||
QString fileDialog(const QVariantMap& properties);
|
||||
|
||||
|
|
Loading…
Reference in a new issue