mirror of
https://github.com/overte-org/overte.git
synced 2025-08-14 14:39:55 +02:00
Merge pull request #12565 from samcake/workload
Workload: Adding view setup job and more debugging tool
This commit is contained in:
commit
ad81fd54f3
19 changed files with 594 additions and 127 deletions
|
@ -4261,14 +4261,7 @@ void Application::idle() {
|
|||
}
|
||||
|
||||
{
|
||||
// TEMP HACK: one view with static radiuses
|
||||
float r0 = 10.0f;
|
||||
float r1 = 20.0f;
|
||||
float r2 = 30.0f;
|
||||
workload::Space::View view(_viewFrustum.getPosition(), r0, r1, r2);
|
||||
std::vector<workload::Space::View> views;
|
||||
views.push_back(view);
|
||||
getEntities()->getWorkloadSpace()->setViews(views);
|
||||
_gameWorkload.updateViews(_viewFrustum);
|
||||
_gameWorkload._engine->run();
|
||||
}
|
||||
{
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
//
|
||||
#include "GameWorkload.h"
|
||||
#include "GameWorkloadRenderer.h"
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
GameWorkloadContext::GameWorkloadContext(const workload::SpacePointer& space, const render::ScenePointer& scene) : WorkloadContext(space), _scene(scene) {
|
||||
}
|
||||
|
@ -36,5 +37,9 @@ void GameWorkload::shutdown() {
|
|||
_engine.reset();
|
||||
}
|
||||
|
||||
|
||||
void GameWorkload::updateViews(const ViewFrustum& frustum) {
|
||||
workload::Views views;
|
||||
views.emplace_back(workload::View::evalFromFrustum(frustum));
|
||||
_engine->feedInput(views);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,8 @@ public:
|
|||
void startup(const workload::SpacePointer& space, const render::ScenePointer& scene);
|
||||
void shutdown();
|
||||
|
||||
void updateViews(const ViewFrustum& frustum);
|
||||
|
||||
workload::EnginePointer _engine;
|
||||
};
|
||||
|
||||
|
|
|
@ -16,11 +16,14 @@
|
|||
#include <GeometryCache.h>
|
||||
|
||||
#include "render-utils/drawWorkloadProxy_vert.h"
|
||||
#include "render-utils/drawWorkloadView_vert.h"
|
||||
#include "render-utils/drawWorkloadProxy_frag.h"
|
||||
|
||||
|
||||
void GameSpaceToRender::configure(const Config& config) {
|
||||
_showAllProxies = config.showAllProxies;
|
||||
_freezeViews = config.freezeViews;
|
||||
_showAllProxies = config.showProxies;
|
||||
_showAllViews = config.showViews;
|
||||
}
|
||||
|
||||
void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext, Outputs& outputs) {
|
||||
|
@ -33,7 +36,11 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext,
|
|||
return;
|
||||
}
|
||||
|
||||
auto visible = _showAllProxies;
|
||||
auto visible = _showAllProxies || _showAllViews;
|
||||
auto showProxies = _showAllProxies;
|
||||
auto showViews = _showAllViews;
|
||||
auto freezeViews = _freezeViews;
|
||||
|
||||
render::Transaction transaction;
|
||||
auto scene = gameWorkloadContext->_scene;
|
||||
|
||||
|
@ -51,22 +58,30 @@ void GameSpaceToRender::run(const workload::WorkloadContextPointer& runContext,
|
|||
std::vector<workload::Space::Proxy> proxies(space->getNumAllocatedProxies());
|
||||
space->copyProxyValues(proxies.data(), (uint32_t)proxies.size());
|
||||
|
||||
|
||||
workload::Views views(space->getNumViews());
|
||||
if (!freezeViews) {
|
||||
space->copyViews(views);
|
||||
}
|
||||
|
||||
// Valid space, let's display its content
|
||||
if (!render::Item::isValidID(_spaceRenderItemID)) {
|
||||
_spaceRenderItemID = scene->allocateID();
|
||||
auto renderItem = std::make_shared<GameWorkloadRenderItem>();
|
||||
renderItem->editBound().setBox(glm::vec3(-100.0f), 200.0f);
|
||||
renderItem->setVisible(visible);
|
||||
renderItem->setAllProxies(proxies);
|
||||
transaction.resetItem(_spaceRenderItemID, std::make_shared<GameWorkloadRenderItem::Payload>(renderItem));
|
||||
} else {
|
||||
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [visible, proxies](GameWorkloadRenderItem& item) {
|
||||
item.setVisible(visible);
|
||||
item.setAllProxies(proxies);
|
||||
});
|
||||
}
|
||||
|
||||
transaction.updateItem<GameWorkloadRenderItem>(_spaceRenderItemID, [visible, showProxies, proxies, freezeViews, showViews, views](GameWorkloadRenderItem& item) {
|
||||
item.setVisible(visible);
|
||||
item.showProxies(showProxies);
|
||||
item.setAllProxies(proxies);
|
||||
item.showViews(showViews);
|
||||
if (!freezeViews) {
|
||||
item.setAllViews(views);
|
||||
}
|
||||
});
|
||||
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
|
||||
|
@ -109,6 +124,15 @@ void GameWorkloadRenderItem::setVisible(bool isVisible) {
|
|||
}
|
||||
}
|
||||
|
||||
void GameWorkloadRenderItem::showProxies(bool show) {
|
||||
_showProxies = show;
|
||||
}
|
||||
|
||||
void GameWorkloadRenderItem::showViews(bool show) {
|
||||
_showViews = show;
|
||||
}
|
||||
|
||||
|
||||
void GameWorkloadRenderItem::setAllProxies(const std::vector<workload::Space::Proxy>& proxies) {
|
||||
_myOwnProxies = proxies;
|
||||
static const uint32_t sizeOfProxy = sizeof(workload::Space::Proxy);
|
||||
|
@ -120,7 +144,18 @@ void GameWorkloadRenderItem::setAllProxies(const std::vector<workload::Space::Pr
|
|||
_numAllProxies = (uint32_t) proxies.size();
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() {
|
||||
void GameWorkloadRenderItem::setAllViews(const workload::Views& views) {
|
||||
_myOwnViews = views;
|
||||
static const uint32_t sizeOfView = sizeof(workload::View);
|
||||
if (!_allViewsBuffer) {
|
||||
_allViewsBuffer = std::make_shared<gpu::Buffer>(sizeOfView);
|
||||
}
|
||||
|
||||
_allViewsBuffer->setData(views.size() * sizeOfView, (const gpu::Byte*) views.data());
|
||||
_numAllViews = (uint32_t)views.size();
|
||||
}
|
||||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getProxiesPipeline() {
|
||||
if (!_drawAllProxiesPipeline) {
|
||||
auto vs = drawWorkloadProxy_vert::getShader();
|
||||
auto ps = drawWorkloadProxy_frag::getShader();
|
||||
|
@ -143,27 +178,56 @@ const gpu::PipelinePointer GameWorkloadRenderItem::getPipeline() {
|
|||
return _drawAllProxiesPipeline;
|
||||
}
|
||||
|
||||
|
||||
const gpu::PipelinePointer GameWorkloadRenderItem::getViewsPipeline() {
|
||||
if (!_drawAllViewsPipeline) {
|
||||
auto vs = drawWorkloadView_vert::getShader();
|
||||
auto ps = drawWorkloadProxy_frag::getShader();
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(vs, ps);
|
||||
|
||||
gpu::Shader::BindingSet slotBindings;
|
||||
slotBindings.insert(gpu::Shader::Binding("workloadViewsBuffer", 1));
|
||||
gpu::Shader::makeProgram(*program, slotBindings);
|
||||
|
||||
auto state = std::make_shared<gpu::State>();
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
/* state->setBlendFunction(true,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::DEST_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ZERO);*/
|
||||
|
||||
PrepareStencil::testMaskDrawShape(*state);
|
||||
state->setCullMode(gpu::State::CULL_NONE);
|
||||
_drawAllViewsPipeline = gpu::Pipeline::create(program, state);
|
||||
}
|
||||
return _drawAllViewsPipeline;
|
||||
}
|
||||
void GameWorkloadRenderItem::render(RenderArgs* args) {
|
||||
gpu::Batch& batch = *(args->_batch);
|
||||
|
||||
// Setup projection
|
||||
glm::mat4 projMat;
|
||||
Transform viewMat;
|
||||
args->getViewFrustum().evalProjectionMatrix(projMat);
|
||||
args->getViewFrustum().evalViewTransform(viewMat);
|
||||
batch.setProjectionTransform(projMat);
|
||||
batch.setViewTransform(viewMat);
|
||||
batch.setModelTransform(Transform());
|
||||
|
||||
// Bind program
|
||||
batch.setPipeline(getPipeline());
|
||||
|
||||
batch.setResourceBuffer(0, _allProxiesBuffer);
|
||||
batch.setResourceBuffer(1, _allViewsBuffer);
|
||||
|
||||
static const int NUM_VERTICES_PER_QUAD = 3;
|
||||
batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_QUAD * _numAllProxies, 0);
|
||||
// Show Proxies
|
||||
if (_showProxies) {
|
||||
batch.setPipeline(getProxiesPipeline());
|
||||
|
||||
static const int NUM_VERTICES_PER_PROXY = 3;
|
||||
batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_PROXY * _numAllProxies, 0);
|
||||
}
|
||||
|
||||
// Show Views
|
||||
if (_showViews) {
|
||||
batch.setPipeline(getViewsPipeline());
|
||||
|
||||
static const int NUM_VERTICES_PER_VIEW = 27;
|
||||
batch.draw(gpu::TRIANGLES, NUM_VERTICES_PER_VIEW * _numAllViews, 0);
|
||||
}
|
||||
|
||||
batch.setResourceBuffer(0, nullptr);
|
||||
batch.setResourceBuffer(1, nullptr);
|
||||
|
||||
batch.setResourceBuffer(11, nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -14,10 +14,14 @@
|
|||
|
||||
class GameSpaceToRenderConfig : public workload::Job::Config {
|
||||
Q_OBJECT
|
||||
Q_PROPERTY(bool showAllProxies MEMBER showAllProxies NOTIFY dirty)
|
||||
Q_PROPERTY(bool freezeViews MEMBER freezeViews NOTIFY dirty)
|
||||
Q_PROPERTY(bool showProxies MEMBER showProxies NOTIFY dirty)
|
||||
Q_PROPERTY(bool showViews MEMBER showViews NOTIFY dirty)
|
||||
public:
|
||||
|
||||
bool showAllProxies{ false };
|
||||
bool freezeViews{ false };
|
||||
bool showProxies{ false };
|
||||
bool showViews{ false };
|
||||
signals:
|
||||
void dirty();
|
||||
|
||||
|
@ -37,7 +41,9 @@ public:
|
|||
|
||||
protected:
|
||||
render::ItemID _spaceRenderItemID{ render::Item::INVALID_ITEM_ID };
|
||||
bool _freezeViews{ false };
|
||||
bool _showAllProxies{ false };
|
||||
bool _showAllViews{ false };
|
||||
};
|
||||
|
||||
|
||||
|
@ -50,12 +56,15 @@ public:
|
|||
~GameWorkloadRenderItem() {}
|
||||
void render(RenderArgs* args);
|
||||
|
||||
render::Item::Bound& editBound() { _needUpdate = true; return _bound; }
|
||||
render::Item::Bound& editBound() { return _bound; }
|
||||
const render::Item::Bound& getBound() { return _bound; }
|
||||
|
||||
void setVisible(bool visible);
|
||||
void showProxies(bool show);
|
||||
void showViews(bool show);
|
||||
|
||||
void setAllProxies(const std::vector<workload::Space::Proxy>& proxies);
|
||||
void setAllViews(const workload::Views& views);
|
||||
|
||||
render::ItemKey getKey() const;
|
||||
|
||||
|
@ -66,12 +75,19 @@ protected:
|
|||
gpu::BufferPointer _allProxiesBuffer;
|
||||
uint32_t _numAllProxies{ 0 };
|
||||
|
||||
workload::Views _myOwnViews;
|
||||
gpu::BufferPointer _allViewsBuffer;
|
||||
uint32_t _numAllViews{ 0 };
|
||||
|
||||
gpu::PipelinePointer _drawAllProxiesPipeline;
|
||||
const gpu::PipelinePointer getPipeline();
|
||||
const gpu::PipelinePointer getProxiesPipeline();
|
||||
|
||||
gpu::PipelinePointer _drawAllViewsPipeline;
|
||||
const gpu::PipelinePointer getViewsPipeline();
|
||||
|
||||
render::ItemKey _key;
|
||||
bool _needUpdate{ true };
|
||||
bool _isVisible{ true };
|
||||
bool _showProxies{ true };
|
||||
bool _showViews{ true };
|
||||
};
|
||||
|
||||
namespace render {
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
<@include gpu/Paint.slh@>
|
||||
|
||||
in vec4 varColor;
|
||||
in vec2 varTexcoord;
|
||||
in vec3 varTexcoord;
|
||||
|
||||
void main(void) {
|
||||
float r = sqrt(dot(varTexcoord.xy,varTexcoord.xy));
|
||||
float r = sqrt(dot(varTexcoord.xyz,varTexcoord.xyz));
|
||||
float a = paintStripe(r * varColor.w, 0.0, 1.0 / varColor.w, 0.05 / varColor.w);
|
||||
if (a <= 0.1 || r > 1.1) {
|
||||
discard;
|
||||
|
|
|
@ -48,7 +48,7 @@ WorkloadProxy getWorkloadProxy(int i) {
|
|||
|
||||
|
||||
out vec4 varColor;
|
||||
out vec2 varTexcoord;
|
||||
out vec3 varTexcoord;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_SPRITE[3] = vec4[3](
|
||||
|
@ -80,7 +80,7 @@ void main(void) {
|
|||
// vec3 dirY = normalize(cross(dirZ, vec3(1.0, 0.0, 0.0)));
|
||||
|
||||
vec4 pos = vec4(proxyPosEye.xyz + proxy.sphere.w * ( dirX * spriteVert.x + dirY * spriteVert.y /* + dirZ * spriteVert.z*/), 1.0);
|
||||
varTexcoord = spriteVert.xy;
|
||||
varTexcoord = spriteVert.xyz;
|
||||
<$transformEyeToClipPos(cam, pos, gl_Position)$>
|
||||
|
||||
// Convert region to color
|
||||
|
|
121
libraries/render-utils/src/drawWorkloadView.slv
Normal file
121
libraries/render-utils/src/drawWorkloadView.slv
Normal file
|
@ -0,0 +1,121 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// drawItemBounds.slv
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Sam Gateau on 6/29/2015.
|
||||
// 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
|
||||
//
|
||||
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include gpu/Color.slh@>
|
||||
<$declareColorWheel()$>
|
||||
|
||||
uniform vec4 inColor;
|
||||
|
||||
|
||||
struct WorkloadView {
|
||||
vec4 direction_far;
|
||||
vec4 fov;
|
||||
vec4 origin;
|
||||
vec4 regions[3];
|
||||
};
|
||||
|
||||
#if defined(GPU_GL410)
|
||||
uniform samplerBuffer workloadViewsBuffer;
|
||||
WorkloadView getWorkloadView(int i) {
|
||||
int offset = 2 * i;
|
||||
WorkloadView view;
|
||||
view.origin = texelFetch(workloadViewsBuffer, offset);
|
||||
view.radiuses = texelFetch(workloadViewsBuffer, offset + 1);
|
||||
return view;
|
||||
}
|
||||
#else
|
||||
layout(std140) buffer workloadViewsBuffer {
|
||||
WorkloadView _views[];
|
||||
};
|
||||
WorkloadView getWorkloadView(int i) {
|
||||
WorkloadView view = _views[i];
|
||||
return view;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
out vec4 varColor;
|
||||
out vec3 varTexcoord;
|
||||
|
||||
const int NUM_VERTICES_PER_VIEW = 27;
|
||||
const int NUM_REGIONS_PER_VIEW = 3;
|
||||
const int NUM_VERTICES_PER_VIEW_REGION = NUM_VERTICES_PER_VIEW / NUM_REGIONS_PER_VIEW;
|
||||
|
||||
void main(void) {
|
||||
const vec4 UNIT_SPRITE[NUM_VERTICES_PER_VIEW_REGION] = vec4[NUM_VERTICES_PER_VIEW_REGION](
|
||||
vec4(-1.0, -1.0, 0.0, 1.0),
|
||||
vec4(3.0, -1.0, 0.0, 1.0),
|
||||
vec4(-1.0, 3.0, 0.0, 1.0),
|
||||
|
||||
vec4(-1.0, 0.0, -1.0, 1.0),
|
||||
vec4(3.0, 0.0, -1.0, 1.0),
|
||||
vec4(-1.0, 0.0, 3.0, 1.0),
|
||||
|
||||
vec4(0.0, -1.0, -1.0, 1.0),
|
||||
vec4(0.0, 3.0, -1.0, 1.0),
|
||||
vec4(0.0, -1.0, 3.0, 1.0)
|
||||
);
|
||||
const int UNIT_SPRITE_INDICES[NUM_VERTICES_PER_VIEW_REGION] = int[NUM_VERTICES_PER_VIEW_REGION](
|
||||
0, 1, 2, 3, 4, 5, 6, 7, 8
|
||||
);
|
||||
|
||||
int viewID = gl_VertexID / NUM_VERTICES_PER_VIEW;
|
||||
int viewVertexID = gl_VertexID - viewID * NUM_VERTICES_PER_VIEW;
|
||||
|
||||
int regionID = viewVertexID / NUM_VERTICES_PER_VIEW_REGION;
|
||||
int regionVertexID = viewVertexID - regionID * NUM_VERTICES_PER_VIEW_REGION;
|
||||
|
||||
int vertexID = regionVertexID;
|
||||
|
||||
vec4 spriteVert = UNIT_SPRITE[UNIT_SPRITE_INDICES[vertexID]];
|
||||
|
||||
WorkloadView view = getWorkloadView(viewID);
|
||||
|
||||
vec4 region = view.regions[regionID];
|
||||
|
||||
vec4 proxyPosWorld = vec4(region.xyz, 1.0);
|
||||
|
||||
// standard transform, bring proxy in view space
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
vec4 proxyPosEye;
|
||||
<$transformModelToEyePos(cam, obj, proxyPosWorld, proxyPosEye)$>
|
||||
|
||||
// Define the billboarded space
|
||||
vec3 dirZ = vec3(0.0, 0.0, 1.0);
|
||||
vec3 dirX = vec3(1.0, 0.0, 0.0);
|
||||
vec3 dirY = vec3(0.0, 1.0, 0.0);
|
||||
|
||||
/*normalize(cross(vec3(0.0, 1.0, 0.0), dirZ));
|
||||
if (dot(proxyPosEye.xyz, proxyPosEye.xyz) > 0.01) {
|
||||
dirZ = -normalize(proxyPosEye.xyz);
|
||||
}
|
||||
vec3 dirX = normalize(cross(vec3(0.0, 1.0, 0.0), dirZ));
|
||||
vec3 dirY = normalize(cross(dirZ, dirX));
|
||||
*/
|
||||
float regionRadius = region.w;
|
||||
|
||||
vec3 originSpaceVert = dirY * (-0.02) + regionRadius * ( dirX * spriteVert.x + dirY * spriteVert.y + dirZ * spriteVert.z);
|
||||
|
||||
vec4 pos = vec4(proxyPosEye.xyz + originSpaceVert, 1.0);
|
||||
varTexcoord = spriteVert.xyz;
|
||||
<$transformEyeToClipPos(cam, pos, gl_Position)$>
|
||||
|
||||
// Convert region to color
|
||||
varColor = vec4(colorWheel(float(regionID) / 4.0), regionRadius);
|
||||
}
|
|
@ -78,6 +78,7 @@ public:
|
|||
|
||||
virtual const Varying getInput() const { return Varying(); }
|
||||
virtual const Varying getOutput() const { return Varying(); }
|
||||
virtual Varying& editInput() = 0;
|
||||
|
||||
virtual QConfigPointer& getConfiguration() { return _config; }
|
||||
virtual void applyConfiguration() = 0;
|
||||
|
@ -141,6 +142,7 @@ public:
|
|||
|
||||
const Varying getInput() const override { return _input; }
|
||||
const Varying getOutput() const override { return _output; }
|
||||
Varying& editInput() override { return _input; }
|
||||
|
||||
template <class... A>
|
||||
Model(const Varying& input, QConfigPointer config, A&&... args) :
|
||||
|
@ -177,6 +179,10 @@ public:
|
|||
|
||||
const Varying getInput() const { return _concept->getInput(); }
|
||||
const Varying getOutput() const { return _concept->getOutput(); }
|
||||
|
||||
template <class I> void feedInput(const I& in) { _concept->editInput().template edit<I>() = in; }
|
||||
|
||||
|
||||
QConfigPointer& getConfiguration() const { return _concept->getConfiguration(); }
|
||||
void applyConfiguration() { return _concept->applyConfiguration(); }
|
||||
|
||||
|
@ -240,6 +246,8 @@ public:
|
|||
|
||||
const Varying getInput() const override { return _input; }
|
||||
const Varying getOutput() const override { return _output; }
|
||||
Varying& editInput() override { return _input; }
|
||||
|
||||
typename Jobs::iterator editJob(std::string name) {
|
||||
typename Jobs::iterator jobIt;
|
||||
for (jobIt = _jobs.begin(); jobIt != _jobs.end(); ++jobIt) {
|
||||
|
|
|
@ -23,10 +23,10 @@ void ClassificationTracker::run(const WorkloadContextPointer& context, Outputs&
|
|||
if (space) {
|
||||
Changes changes;
|
||||
space->categorizeAndGetChanges(changes);
|
||||
outputs.resize(workload::Space::NUM_TRANSITIONS);
|
||||
outputs.resize(workload::Region::NUM_TRANSITIONS);
|
||||
for (uint32_t i = 0; i < changes.size(); ++i) {
|
||||
int32_t j = Space::computeTransitionIndex(changes[i].prevRegion, changes[i].region);
|
||||
assert(j >= 0 && j < workload::Space::NUM_TRANSITIONS);
|
||||
int32_t j = Region::computeTransitionIndex(changes[i].prevRegion, changes[i].region);
|
||||
assert(j >= 0 && j < workload::Region::NUM_TRANSITIONS);
|
||||
outputs[j].push_back(changes[i].proxyId);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,23 +16,45 @@
|
|||
|
||||
#include <iostream>
|
||||
|
||||
#include "ViewTask.h"
|
||||
#include "ClassificationTracker.h"
|
||||
|
||||
namespace workload {
|
||||
class DebugCout {
|
||||
public:
|
||||
using Inputs = SortedChanges;
|
||||
using JobModel = workload::Job::ModelI<DebugCout, Inputs>;
|
||||
|
||||
DebugCout() {}
|
||||
|
||||
void run(const workload::WorkloadContextPointer& renderContext, const Inputs& inputs) {
|
||||
qDebug() << "Some message from " << inputs.size();
|
||||
int i = 0;
|
||||
for (auto& b: inputs) {
|
||||
qDebug() << " Bucket Number" << i << " size is " << b.size();
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
};
|
||||
|
||||
|
||||
WorkloadContext::WorkloadContext(const SpacePointer& space) : task::JobContext(trace_workload()), _space(space) {}
|
||||
|
||||
using EngineModel = Task::Model<class EngineBuilder>;
|
||||
|
||||
class EngineBuilder {
|
||||
public:
|
||||
using JobModel = Task::Model<EngineModel>;
|
||||
void build(EngineModel& model, const Varying& in, Varying& out) {
|
||||
auto classifications = model.addJob<ClassificationTracker>("classificationTracker");
|
||||
using Inputs = Views;
|
||||
using JobModel = Task::ModelI<EngineBuilder, Inputs>;
|
||||
void build(JobModel& model, const Varying& in, Varying& out) {
|
||||
model.addJob<SetupViews>("setupViews", in);
|
||||
const auto classifications = model.addJob<ClassificationTracker>("classificationTracker");
|
||||
// model.addJob<DebugCout>("debug", classifications);
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineModel::create()),
|
||||
Engine::Engine(const WorkloadContextPointer& context) : Task("Engine", EngineBuilder::JobModel::create()),
|
||||
_context(context) {
|
||||
}
|
||||
} // namespace workload
|
||||
|
|
74
libraries/workload/src/workload/Region.h
Normal file
74
libraries/workload/src/workload/Region.h
Normal file
|
@ -0,0 +1,74 @@
|
|||
//
|
||||
// Region.h
|
||||
// libraries/workload/src/workload
|
||||
//
|
||||
// Created by Sam Gateau 2018.03.05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_workload_Region_h
|
||||
#define hifi_workload_Region_h
|
||||
|
||||
namespace workload {
|
||||
|
||||
class Region {
|
||||
public:
|
||||
using Type = uint8_t;
|
||||
|
||||
enum Name : uint8_t {
|
||||
R1 = 0,
|
||||
R2,
|
||||
R3,
|
||||
UNKNOWN,
|
||||
INVALID,
|
||||
};
|
||||
|
||||
static const uint8_t NUM_CLASSIFICATIONS = 4;
|
||||
static const uint8_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1);
|
||||
|
||||
static const uint8_t NUM_VIEW_REGIONS = (NUM_CLASSIFICATIONS - 1);
|
||||
|
||||
static uint8_t computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex);
|
||||
|
||||
};
|
||||
|
||||
inline uint8_t Region::computeTransitionIndex(uint8_t prevIndex, uint8_t newIndex) {
|
||||
// given prevIndex and newIndex compute an index into the transition list,
|
||||
// where the lists between unchanged indices don't exist (signaled by index = -1).
|
||||
//
|
||||
// Given an NxN array
|
||||
// let p = i + N * j
|
||||
//
|
||||
// then k = -1 when i == j
|
||||
// = p - (1 + p/(N+1)) when i != j
|
||||
//
|
||||
// i 0 1 2 3
|
||||
// j +-------+-------+-------+-------+
|
||||
// |p = 0 | 1 | 2 | 3 |
|
||||
// 0 | | | | |
|
||||
// |k = -1 | 0 | 1 | 2 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 4 | 5 | 6 | 7 |
|
||||
// 1 | | | | |
|
||||
// | 3 | -1 | 4 | 5 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 8 | 9 | 10 | 11 |
|
||||
// 2 | | | | |
|
||||
// | 6 | 7 | -1 | 8 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 12 | 13 | 14 | 15 |
|
||||
// 3 | | | | |
|
||||
// | 9 | 10 | 11 | -1 |
|
||||
// +-------+-------+-------+-------+
|
||||
uint8_t p = prevIndex + Region::NUM_CLASSIFICATIONS * newIndex;
|
||||
if (0 == (p % (Region::NUM_CLASSIFICATIONS + 1))) {
|
||||
return -1;
|
||||
}
|
||||
return p - (1 + p / (Region::NUM_CLASSIFICATIONS + 1));
|
||||
}
|
||||
|
||||
} // namespace workload
|
||||
|
||||
#endif // hifi_workload_Region_h
|
|
@ -33,8 +33,8 @@ int32_t Space::createProxy(const Space::Sphere& newSphere) {
|
|||
int32_t index = _freeIndices.back();
|
||||
_freeIndices.pop_back();
|
||||
_proxies[index].sphere = newSphere;
|
||||
_proxies[index].region = Space::REGION_UNKNOWN;
|
||||
_proxies[index].prevRegion = Space::REGION_UNKNOWN;
|
||||
_proxies[index].region = Region::UNKNOWN;
|
||||
_proxies[index].prevRegion = Region::UNKNOWN;
|
||||
return index;
|
||||
}
|
||||
}
|
||||
|
@ -54,24 +54,39 @@ void Space::updateProxies(const std::vector<ProxyUpdate>& changedProxies) {
|
|||
}
|
||||
}
|
||||
|
||||
void Space::setViews(const std::vector<Space::View>& views) {
|
||||
void Space::setViews(const Views& views) {
|
||||
_views = views;
|
||||
}
|
||||
|
||||
void Space::copyViews(std::vector<View>& copy) const {
|
||||
copy = _views;
|
||||
}
|
||||
|
||||
// TODO?: move this to an algorithm/job?
|
||||
void Space::categorizeAndGetChanges(std::vector<Space::Change>& changes) {
|
||||
uint32_t numProxies = (uint32_t)_proxies.size();
|
||||
uint32_t numViews = (uint32_t)_views.size();
|
||||
for (uint32_t i = 0; i < numProxies; ++i) {
|
||||
Proxy& proxy = _proxies[i];
|
||||
if (proxy.region < Space::REGION_INVALID) {
|
||||
uint8_t region = Space::REGION_UNKNOWN;
|
||||
if (proxy.region < Region::INVALID) {
|
||||
uint8_t region = Region::UNKNOWN;
|
||||
for (uint32_t j = 0; j < numViews; ++j) {
|
||||
float distance2 = glm::distance2(_views[j].center, glm::vec3(_proxies[i].sphere));
|
||||
for (uint8_t c = 0; c < region; ++c) {
|
||||
float touchDistance = _views[j].radiuses[c] + _proxies[i].sphere.w;
|
||||
if (distance2 < touchDistance * touchDistance) {
|
||||
region = c;
|
||||
auto& view = _views[j];
|
||||
|
||||
glm::vec3 distance2(glm::distance2(proxy.sphere, view.regions[0]), glm::distance2(proxy.sphere, view.regions[1]), glm::distance2(proxy.sphere, view.regions[2]));
|
||||
glm::vec3 regionRadii2(view.regions[0].w + proxy.sphere.w, view.regions[1].w + proxy.sphere.w, view.regions[2].w + proxy.sphere.w);
|
||||
regionRadii2 *= regionRadii2;
|
||||
auto touchTests = glm::lessThanEqual(distance2, regionRadii2);
|
||||
|
||||
if (glm::any(touchTests)) {
|
||||
if (touchTests.x) {
|
||||
region = Region::R1;
|
||||
break;
|
||||
} else if (touchTests.y) {
|
||||
region = Region::R2;
|
||||
break;
|
||||
} else {
|
||||
region = Region::R3;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -100,13 +115,13 @@ void Space::deleteProxy(int32_t proxyId) {
|
|||
}
|
||||
}
|
||||
} else {
|
||||
_proxies[proxyId].region = Space::REGION_INVALID;
|
||||
_proxies[proxyId].region = Region::INVALID;
|
||||
_freeIndices.push_back(proxyId);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) {
|
||||
uint32_t Space::copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const {
|
||||
|
||||
auto numCopied = std::min(numDestProxies, (uint32_t)_proxies.size());
|
||||
memcpy(proxies, _proxies.data(), numCopied * sizeof(Proxy));
|
||||
|
|
|
@ -19,22 +19,13 @@
|
|||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "View.h"
|
||||
|
||||
|
||||
namespace workload {
|
||||
|
||||
class Space {
|
||||
public:
|
||||
static const int32_t NUM_CLASSIFICATIONS = 4;
|
||||
static const int32_t NUM_TRANSITIONS = NUM_CLASSIFICATIONS * (NUM_CLASSIFICATIONS - 1);
|
||||
|
||||
static int32_t computeTransitionIndex(int32_t prevIndex, int32_t newIndex);
|
||||
|
||||
static const uint8_t REGION_NEAR = 0;
|
||||
static const uint8_t REGION_MIDDLE = 1;
|
||||
static const uint8_t REGION_FAR = 2;
|
||||
static const uint8_t REGION_UNKNOWN = 3;
|
||||
static const uint8_t REGION_INVALID = 4;
|
||||
|
||||
using Sphere = glm::vec4; // <x,y,z> = center, w = radius
|
||||
using ProxyUpdate = std::pair<int32_t, Sphere>;
|
||||
|
||||
|
@ -43,23 +34,12 @@ public:
|
|||
Proxy() : sphere(0.0f) {}
|
||||
Proxy(const Sphere& s) : sphere(s) {}
|
||||
Sphere sphere;
|
||||
uint8_t region { REGION_UNKNOWN };
|
||||
uint8_t prevRegion { REGION_UNKNOWN };
|
||||
uint8_t region { Region::UNKNOWN };
|
||||
uint8_t prevRegion { Region::UNKNOWN };
|
||||
uint16_t _padding;
|
||||
uint32_t _paddings[3];
|
||||
};
|
||||
|
||||
class View {
|
||||
public:
|
||||
View(const glm::vec3& pos, float nearRadius, float midRadius, float farRadius) : center(pos) {
|
||||
radiuses[REGION_NEAR] = nearRadius;
|
||||
radiuses[REGION_MIDDLE] = midRadius;
|
||||
radiuses[REGION_FAR] = farRadius;
|
||||
}
|
||||
glm::vec3 center;
|
||||
float radiuses[NUM_CLASSIFICATIONS - 1];
|
||||
};
|
||||
|
||||
class Change {
|
||||
public:
|
||||
Change(int32_t i, uint32_t c, uint32_t p) : proxyId(i), region(c), prevRegion(p) {}
|
||||
|
@ -76,56 +56,25 @@ public:
|
|||
void updateProxies(const std::vector<ProxyUpdate>& changedProxies);
|
||||
void setViews(const std::vector<View>& views);
|
||||
|
||||
uint32_t getNumViews() const { return (uint32_t)(_views.size()); }
|
||||
void copyViews(std::vector<View>& copy) const;
|
||||
|
||||
|
||||
uint32_t getNumObjects() const { return (uint32_t)(_proxies.size() - _freeIndices.size()); }
|
||||
uint32_t getNumAllocatedProxies() const { return (uint32_t)(_proxies.size()); }
|
||||
|
||||
void categorizeAndGetChanges(std::vector<Change>& changes);
|
||||
uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies);
|
||||
uint32_t copyProxyValues(Proxy* proxies, uint32_t numDestProxies) const;
|
||||
|
||||
private:
|
||||
void deleteProxy(int32_t proxyId);
|
||||
void updateProxy(int32_t proxyId, const Sphere& sphere);
|
||||
|
||||
std::vector<Proxy> _proxies;
|
||||
std::vector<View> _views;
|
||||
Views _views;
|
||||
std::vector<int32_t> _freeIndices;
|
||||
};
|
||||
|
||||
inline int32_t Space::computeTransitionIndex(int32_t prevIndex, int32_t newIndex) {
|
||||
// given prevIndex and newIndex compute an index into the transition list,
|
||||
// where the lists between unchanged indices don't exist (signaled by index = -1).
|
||||
//
|
||||
// Given an NxN array
|
||||
// let p = i + N * j
|
||||
//
|
||||
// then k = -1 when i == j
|
||||
// = p - (1 + p/(N+1)) when i != j
|
||||
//
|
||||
// i 0 1 2 3
|
||||
// j +-------+-------+-------+-------+
|
||||
// |p = 0 | 1 | 2 | 3 |
|
||||
// 0 | | | | |
|
||||
// |k = -1 | 0 | 1 | 2 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 4 | 5 | 6 | 7 |
|
||||
// 1 | | | | |
|
||||
// | 3 | -1 | 4 | 5 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 8 | 9 | 10 | 11 |
|
||||
// 2 | | | | |
|
||||
// | 6 | 7 | -1 | 8 |
|
||||
// +-------+-------+-------+-------+
|
||||
// | 12 | 13 | 14 | 15 |
|
||||
// 3 | | | | |
|
||||
// | 9 | 10 | 11 | -1 |
|
||||
// +-------+-------+-------+-------+
|
||||
int32_t p = prevIndex + Space::NUM_CLASSIFICATIONS * newIndex;
|
||||
if (0 == (p % (Space::NUM_CLASSIFICATIONS + 1))) {
|
||||
return -1;
|
||||
}
|
||||
return p - (1 + p / (Space::NUM_CLASSIFICATIONS + 1));
|
||||
}
|
||||
|
||||
using SpacePointer = std::shared_ptr<Space>;
|
||||
using Changes = std::vector<Space::Change>;
|
||||
using SortedChanges = std::vector<std::vector<int32_t>>;
|
||||
|
|
48
libraries/workload/src/workload/View.cpp
Normal file
48
libraries/workload/src/workload/View.cpp
Normal file
|
@ -0,0 +1,48 @@
|
|||
//
|
||||
// View.cpp
|
||||
// libraries/workload/src/workload
|
||||
//
|
||||
// Created by Sam Gateau 2018.03.05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "View.h"
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
using namespace workload;
|
||||
|
||||
void View::setFov(float angleRad) {
|
||||
float halfAngle = angleRad * 0.5f;
|
||||
|
||||
fov_halfAngle_tan_cos_sin.x = halfAngle;
|
||||
fov_halfAngle_tan_cos_sin.y = tanf(halfAngle);
|
||||
fov_halfAngle_tan_cos_sin.z = cosf(halfAngle);
|
||||
fov_halfAngle_tan_cos_sin.w = sinf(halfAngle);
|
||||
}
|
||||
|
||||
View View::evalFromFrustum(const ViewFrustum& frustum) {
|
||||
View view;
|
||||
view.origin = frustum.getPosition();
|
||||
view.direction = frustum.getDirection();
|
||||
view.setFov(frustum.getFieldOfView());
|
||||
|
||||
return view;
|
||||
}
|
||||
|
||||
Sphere View::evalRegionSphere(const View& view, float originRadius, float maxDistance) {
|
||||
float radius = (maxDistance + originRadius) / 2.0f;
|
||||
float center = radius - originRadius;
|
||||
return Sphere(view.origin + view.direction * center, radius);
|
||||
}
|
||||
|
||||
void View::updateRegions(View& view) {
|
||||
float refFar = 10.0f;
|
||||
float refClose = 2.0f;
|
||||
for (int i = 0; i < Region::NUM_VIEW_REGIONS; i++) {
|
||||
float weight = i + 1.0f;
|
||||
view.regions[i] = evalRegionSphere(view, refClose * weight, refFar * weight);
|
||||
refFar *= 2.0f;
|
||||
}
|
||||
}
|
66
libraries/workload/src/workload/View.h
Normal file
66
libraries/workload/src/workload/View.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// View.h
|
||||
// libraries/workload/src/workload
|
||||
//
|
||||
// Created by Sam Gateau 2018.03.05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#ifndef hifi_workload_View_h
|
||||
#define hifi_workload_View_h
|
||||
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
#include <glm/glm.hpp>
|
||||
|
||||
#include "Region.h"
|
||||
|
||||
class ViewFrustum;
|
||||
|
||||
namespace workload {
|
||||
|
||||
using Sphere = glm::vec4;
|
||||
|
||||
class View {
|
||||
public:
|
||||
View() = default;
|
||||
View(const View& view) = default;
|
||||
|
||||
// View attributes:
|
||||
|
||||
// direction
|
||||
glm::vec3 direction{ 0.0f, 0.0f, -1.0f };
|
||||
|
||||
// Max radius
|
||||
float maxRadius{ FLT_MAX };
|
||||
|
||||
// Fov stores the half field of view angle, and tan/cos/sin ready to go, default is fov of 90deg
|
||||
glm::vec4 fov_halfAngle_tan_cos_sin { (float) M_PI_4, 1.0f, (float) (M_SQRT2 * 0.5), (float) (M_SQRT2 * 0.5) };
|
||||
|
||||
// Origin position
|
||||
glm::vec3 origin{ 0.0f };
|
||||
|
||||
// Origin radius
|
||||
float originRadius{ 0.5f };
|
||||
|
||||
// N regions spheres
|
||||
Sphere regions[Region::NUM_VIEW_REGIONS];
|
||||
|
||||
// Set fov properties from angle
|
||||
void setFov(float angleRad);
|
||||
|
||||
|
||||
static View evalFromFrustum(const ViewFrustum& frustum);
|
||||
static Sphere evalRegionSphere(const View& view, float originRadius, float maxDistance);
|
||||
|
||||
static void updateRegions(View& view);
|
||||
};
|
||||
|
||||
using Views = std::vector<View>;
|
||||
|
||||
} // namespace workload
|
||||
|
||||
#endif // hifi_workload_View_h
|
28
libraries/workload/src/workload/ViewTask.cpp
Normal file
28
libraries/workload/src/workload/ViewTask.cpp
Normal file
|
@ -0,0 +1,28 @@
|
|||
//
|
||||
// ViewTask.cpp
|
||||
// libraries/workload/src/workload
|
||||
//
|
||||
// Created by Sam Gateau 2018.03.05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#include "ViewTask.h"
|
||||
|
||||
using namespace workload;
|
||||
|
||||
|
||||
void SetupViews::configure(const Config& config) {
|
||||
}
|
||||
|
||||
void SetupViews::run(const WorkloadContextPointer& renderContext, const Input& inputs) {
|
||||
|
||||
Views views = inputs;
|
||||
for (auto& v : views) {
|
||||
View::updateRegions(v);
|
||||
}
|
||||
|
||||
renderContext->_space->setViews(views);
|
||||
}
|
||||
|
35
libraries/workload/src/workload/ViewTask.h
Normal file
35
libraries/workload/src/workload/ViewTask.h
Normal file
|
@ -0,0 +1,35 @@
|
|||
//
|
||||
// ViewTask.h
|
||||
// libraries/workload/src/workload
|
||||
//
|
||||
// Created by Sam Gateau 2018.03.05
|
||||
// Copyright 2018 High Fidelity, Inc.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
#ifndef hifi_workload_ViewTask_h
|
||||
#define hifi_workload_ViewTask_h
|
||||
|
||||
#include "Engine.h"
|
||||
|
||||
namespace workload {
|
||||
class SetupViewsConfig : public Job::Config{
|
||||
Q_OBJECT
|
||||
public:
|
||||
SetupViewsConfig() : Job::Config(true) {}
|
||||
};
|
||||
|
||||
class SetupViews {
|
||||
public:
|
||||
using Config = SetupViewsConfig;
|
||||
using Input = Views;
|
||||
using JobModel = Job::ModelI<SetupViews, Input, Config>;
|
||||
|
||||
void configure(const Config& config);
|
||||
void run(const workload::WorkloadContextPointer& renderContext, const Input& inputs);
|
||||
};
|
||||
|
||||
} // namespace workload
|
||||
|
||||
#endif // hifi_workload_ViewTask_h
|
|
@ -21,6 +21,7 @@ Rectangle {
|
|||
anchors.margins: hifi.dimensions.contentMargin.x
|
||||
|
||||
color: hifi.colors.baseGray;
|
||||
property var setupViews: Workload.getConfig("setupViews")
|
||||
property var spaceToRender: Workload.getConfig("SpaceToRender")
|
||||
|
||||
Column {
|
||||
|
@ -30,11 +31,31 @@ Rectangle {
|
|||
anchors.margins: hifi.dimensions.contentMargin.x
|
||||
//padding: hifi.dimensions.contentMargin.x
|
||||
|
||||
HifiControls.Label {
|
||||
text: "Workload"
|
||||
}
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Show All Proxies"
|
||||
checked: workload.spaceToRender["showAllProxies"]
|
||||
onCheckedChanged: { workload.spaceToRender["showAllProxies"] = checked }
|
||||
text: "Freeze Views"
|
||||
checked: workload.spaceToRender["freezeViews"]
|
||||
onCheckedChanged: { workload.spaceToRender["freezeViews"] = checked, workload.setupViews.enabled = !checked; }
|
||||
}
|
||||
Separator {}
|
||||
HifiControls.Label {
|
||||
text: "Display"
|
||||
}
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Show Proxies"
|
||||
checked: workload.spaceToRender["showProxies"]
|
||||
onCheckedChanged: { workload.spaceToRender["showProxies"] = checked }
|
||||
}
|
||||
HifiControls.CheckBox {
|
||||
boxSize: 20
|
||||
text: "Show Views"
|
||||
checked: workload.spaceToRender["showViews"]
|
||||
onCheckedChanged: { workload.spaceToRender["showViews"] = checked }
|
||||
}
|
||||
Separator {}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue