//// MetavoxelSystem.cpp// interface/src//// Created by Andrzej Kapolka on 12/10/13.// Copyright 2013 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 <QMutexLocker>#include <QReadLocker>#include <QWriteLocker>#include <QtDebug> #include <glm/gtx/transform.hpp> #include <SharedUtil.h> #include <MetavoxelUtil.h>#include <ScriptCache.h> #include "Application.h"#include "MetavoxelSystem.h"#include "renderer/Model.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation)REGISTER_META_OBJECT(SphereRenderer)REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>(); void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); _pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer")); _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( new BufferDataAttribute("heightfieldBuffer"));} MetavoxelLOD MetavoxelSystem::getLOD() { QReadLocker locker(&_lodLock); return _lod;} class SimulateVisitor : public MetavoxelVisitor {public: SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: float _deltaTime;}; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) {} int SimulateVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); return STOP_RECURSION;} void MetavoxelSystem::simulate(float deltaTime) { // update the lod { // the LOD threshold is temporarily tied to the avatar LOD parameter QWriteLocker locker(&_lodLock); const float BASE_LOD_THRESHOLD = 0.01f; _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), BASE_LOD_THRESHOLD * Menu::getInstance()->getAvatarLODDistanceMultiplier()); } SimulateVisitor simulateVisitor(deltaTime, getLOD()); guideToAugmented(simulateVisitor);} class RenderVisitor : public MetavoxelVisitor {public: RenderVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info);}; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod) {} int RenderVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); return STOP_RECURSION;} void MetavoxelSystem::render() { RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor);} MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { return new MetavoxelSystemClient(node, _updater);} void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor) { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast<MetavoxelSystemClient*>(node->getLinkedData()); if (client) { client->getAugmentedData().guide(visitor); } } }} MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : MetavoxelClient(node, updater) {} void MetavoxelSystemClient::setAugmentedData(const MetavoxelData& data) { QWriteLocker locker(&_augmentedDataLock); _augmentedData = data;} MetavoxelData MetavoxelSystemClient::getAugmentedData() { QReadLocker locker(&_augmentedDataLock); return _augmentedData;} int MetavoxelSystemClient::parseData(const QByteArray& packet) { // process through sequencer QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::METAVOXELS).updateValue(packet.size()); return packet.size();} class AugmentVisitor : public MetavoxelVisitor {public: AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData); virtual int visit(MetavoxelInfo& info); private: const MetavoxelData& _previousData;}; AugmentVisitor::AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _previousData(previousData) {} int AugmentVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod); return STOP_RECURSION;} class Augmenter : public QRunnable {public: Augmenter(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelData& previousData, const MetavoxelLOD& lod); virtual void run(); private: QWeakPointer<Node> _node; MetavoxelData _data; MetavoxelData _previousData; MetavoxelLOD _lod;}; Augmenter::Augmenter(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelData& previousData, const MetavoxelLOD& lod) : _node(node), _data(data), _previousData(previousData), _lod(lod) {} void Augmenter::run() { SharedNodePointer node = _node; if (!node) { return; } AugmentVisitor visitor(_lod, _previousData); _data.guide(visitor); QMutexLocker locker(&node->getMutex()); QMetaObject::invokeMethod(node->getLinkedData(), "setAugmentedData", Q_ARG(const MetavoxelData&, _data));} void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) { MetavoxelClient::dataChanged(oldData); QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD));} void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { NodeList::getInstance()->writeDatagram(data, _node); Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size());} BufferData::~BufferData() {} PointBuffer::PointBuffer(const BufferPointVector& points) : _points(points) {} void PointBuffer::render() { // initialize buffer, etc. on first render if (!_buffer.isCreated()) { _buffer.setUsagePattern(QOpenGLBuffer::StaticDraw); _buffer.create(); _buffer.bind(); _pointCount = _points.size(); _buffer.allocate(_points.constData(), _pointCount * sizeof(BufferPoint)); _points.clear(); _buffer.release(); } if (_pointCount == 0) { return; } _buffer.bind(); BufferPoint* point = 0; glVertexPointer(4, GL_FLOAT, sizeof(BufferPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(BufferPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(BufferPoint), &point->normal); glDrawArrays(GL_POINTS, 0, _pointCount); _buffer.release();} HeightfieldBuffer::HeightfieldBuffer(const QByteArray& height, const QByteArray& color, const QByteArray& normal) : _height(height), _color(color), _normal(normal), _heightTexture(QOpenGLTexture::Target2D), _colorTexture(QOpenGLTexture::Target2D), _normalTexture(QOpenGLTexture::Target2D) {} void HeightfieldBuffer::render() { // initialize textures, etc. on first render if (!_heightTexture.isCreated()) { int heightSize = glm::sqrt(_height.size()); _heightTexture.setSize(heightSize, heightSize); _heightTexture.setFormat(QOpenGLTexture::LuminanceFormat); _heightTexture.allocateStorage(); _heightTexture.setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8, _height.data()); _height.clear(); int colorSize = glm::sqrt(_color.size() / 3); _colorTexture.setSize(colorSize, colorSize); _colorTexture.setFormat(QOpenGLTexture::RGBFormat); _colorTexture.allocateStorage(); _colorTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _color.data()); _color.clear(); int normalSize = glm::sqrt(_normal.size() / 3); _normalTexture.setSize(normalSize, normalSize); _normalTexture.setFormat(QOpenGLTexture::RGBFormat); _normalTexture.allocateStorage(); _normalTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _normal.data()); _normal.clear(); } } BufferDataAttribute::BufferDataAttribute(const QString& name) : InlineAttribute<BufferDataPointer>(name) {} bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const { BufferDataPointer firstChild = decodeInline<BufferDataPointer>(children[0]); for (int i = 1; i < MERGE_COUNT; i++) { if (firstChild != decodeInline<BufferDataPointer>(children[i])) { *(BufferDataPointer*)&parent = _defaultValue; return false; } } *(BufferDataPointer*)&parent = firstChild; return true;} void DefaultMetavoxelRendererImplementation::init() { if (!_pointProgram.isLinked()) { _pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert"); _pointProgram.link(); _pointProgram.bind(); _pointScaleLocation = _pointProgram.uniformLocation("pointScale"); _pointProgram.release(); _heightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_heightfield.vert"); _heightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/metavoxel_heightfield.frag"); _heightfieldProgram.link(); }} DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {} class PointAugmentVisitor : public MetavoxelVisitor {public: PointAugmentVisitor(const MetavoxelLOD& lod); virtual void prepare(MetavoxelData* data); virtual int visit(MetavoxelInfo& info); virtual bool postVisit(MetavoxelInfo& info); private: BufferPointVector _points; float _pointLeafSize;}; PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() << AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>() << Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) {} const int ALPHA_RENDER_THRESHOLD = 0; void PointAugmentVisitor::prepare(MetavoxelData* data) { MetavoxelVisitor::prepare(data); const float MAX_POINT_LEAF_SIZE = 64.0f; _pointLeafSize = qMin(data->getSize(), MAX_POINT_LEAF_SIZE);} int PointAugmentVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return (info.size > _pointLeafSize) ? DEFAULT_ORDER : (DEFAULT_ORDER | ALL_NODES_REST); } QRgb color = info.inputValues.at(0).getInlineValue<QRgb>(); quint8 alpha = qAlpha(color); if (alpha > ALPHA_RENDER_THRESHOLD) { QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>(); BufferPoint point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)) }, { quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } }; _points.append(point); } if (info.size >= _pointLeafSize) { BufferPointVector swapPoints; _points.swap(swapPoints); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer( new PointBuffer(swapPoints)))); } return STOP_RECURSION;} bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) { if (info.size != _pointLeafSize) { return false; } BufferPointVector swapPoints; _points.swap(swapPoints); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer( new PointBuffer(swapPoints)))); return true;} class HeightfieldAugmentVisitor : public MetavoxelVisitor {public: HeightfieldAugmentVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info);}; HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>() << Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod) {} int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION;} void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod) { // copy the previous buffers MetavoxelData expandedPrevious = previous; while (expandedPrevious.getSize() < data.getSize()) { expandedPrevious.expand(); } const AttributePointer& pointBufferAttribute = Application::getInstance()->getMetavoxels()->getPointBufferAttribute(); MetavoxelNode* root = expandedPrevious.getRoot(pointBufferAttribute); if (root) { data.setRoot(pointBufferAttribute, root); root->incrementReferenceCount(); } PointAugmentVisitor visitor(lod); data.guideToDifferent(expandedPrevious, visitor); } class SpannerSimulateVisitor : public SpannerVisitor {public: SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); private: float _deltaTime;}; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) {} bool SpannerSimulateVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) { spanner->getRenderer()->simulate(_deltaTime); return true;} void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod) { SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod); data.guide(spannerSimulateVisitor);} class SpannerRenderVisitor : public SpannerVisitor {public: SpannerRenderVisitor(const MetavoxelLOD& lod); virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize);}; SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod, encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {} bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) { spanner->getRenderer()->render(1.0f, SpannerRenderer::DEFAULT_MODE, clipMinimum, clipSize); return true;} class BufferRenderVisitor : public MetavoxelVisitor {public: BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: int _order;}; BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << attribute, QVector<AttributePointer>(), lod), _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {} int BufferRenderVisitor::visit(MetavoxelInfo& info) { BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>(); if (buffer) { buffer->render(); } return info.isLeaf ? STOP_RECURSION : _order;}Lines 1–500 of 685. Load more
// // MetavoxelSystem.cpp // interface/src // // Created by Andrzej Kapolka on 12/10/13. // Copyright 2013 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 <QMutexLocker> #include <QReadLocker> #include <QWriteLocker> #include <QtDebug> #include <glm/gtx/transform.hpp> #include <SharedUtil.h> #include <MetavoxelUtil.h> #include <ScriptCache.h> #include "Application.h" #include "MetavoxelSystem.h" #include "renderer/Model.h" REGISTER_META_OBJECT(DefaultMetavoxelRendererImplementation) REGISTER_META_OBJECT(SphereRenderer) REGISTER_META_OBJECT(StaticModelRenderer) static int bufferPointVectorMetaTypeId = qRegisterMetaType<BufferPointVector>(); void MetavoxelSystem::init() { MetavoxelClientManager::init(); DefaultMetavoxelRendererImplementation::init(); _pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer")); _heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute( new BufferDataAttribute("heightfieldBuffer")); } MetavoxelLOD MetavoxelSystem::getLOD() { QReadLocker locker(&_lodLock); return _lod; } class SimulateVisitor : public MetavoxelVisitor { public: SimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: float _deltaTime; }; SimulateVisitor::SimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) { } int SimulateVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->simulate(*_data, _deltaTime, info, _lod); return STOP_RECURSION; } void MetavoxelSystem::simulate(float deltaTime) { // update the lod { // the LOD threshold is temporarily tied to the avatar LOD parameter QWriteLocker locker(&_lodLock); const float BASE_LOD_THRESHOLD = 0.01f; _lod = MetavoxelLOD(Application::getInstance()->getCamera()->getPosition(), BASE_LOD_THRESHOLD * Menu::getInstance()->getAvatarLODDistanceMultiplier()); } SimulateVisitor simulateVisitor(deltaTime, getLOD()); guideToAugmented(simulateVisitor); } class RenderVisitor : public MetavoxelVisitor { public: RenderVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); }; RenderVisitor::RenderVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod) { } int RenderVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->render(*_data, info, _lod); return STOP_RECURSION; } void MetavoxelSystem::render() { RenderVisitor renderVisitor(getLOD()); guideToAugmented(renderVisitor); } MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { return new MetavoxelSystemClient(node, _updater); } void MetavoxelSystem::guideToAugmented(MetavoxelVisitor& visitor) { foreach (const SharedNodePointer& node, NodeList::getInstance()->getNodeHash()) { if (node->getType() == NodeType::MetavoxelServer) { QMutexLocker locker(&node->getMutex()); MetavoxelSystemClient* client = static_cast<MetavoxelSystemClient*>(node->getLinkedData()); if (client) { client->getAugmentedData().guide(visitor); } } } } MetavoxelSystemClient::MetavoxelSystemClient(const SharedNodePointer& node, MetavoxelUpdater* updater) : MetavoxelClient(node, updater) { } void MetavoxelSystemClient::setAugmentedData(const MetavoxelData& data) { QWriteLocker locker(&_augmentedDataLock); _augmentedData = data; } MetavoxelData MetavoxelSystemClient::getAugmentedData() { QReadLocker locker(&_augmentedDataLock); return _augmentedData; } int MetavoxelSystemClient::parseData(const QByteArray& packet) { // process through sequencer QMetaObject::invokeMethod(&_sequencer, "receivedDatagram", Q_ARG(const QByteArray&, packet)); Application::getInstance()->getBandwidthMeter()->inputStream(BandwidthMeter::METAVOXELS).updateValue(packet.size()); return packet.size(); } class AugmentVisitor : public MetavoxelVisitor { public: AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData); virtual int visit(MetavoxelInfo& info); private: const MetavoxelData& _previousData; }; AugmentVisitor::AugmentVisitor(const MetavoxelLOD& lod, const MetavoxelData& previousData) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getRendererAttribute(), QVector<AttributePointer>(), lod), _previousData(previousData) { } int AugmentVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return DEFAULT_ORDER; } static_cast<MetavoxelRenderer*>(info.inputValues.at(0).getInlineValue< SharedObjectPointer>().data())->getImplementation()->augment(*_data, _previousData, info, _lod); return STOP_RECURSION; } class Augmenter : public QRunnable { public: Augmenter(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelData& previousData, const MetavoxelLOD& lod); virtual void run(); private: QWeakPointer<Node> _node; MetavoxelData _data; MetavoxelData _previousData; MetavoxelLOD _lod; }; Augmenter::Augmenter(const SharedNodePointer& node, const MetavoxelData& data, const MetavoxelData& previousData, const MetavoxelLOD& lod) : _node(node), _data(data), _previousData(previousData), _lod(lod) { } void Augmenter::run() { SharedNodePointer node = _node; if (!node) { return; } AugmentVisitor visitor(_lod, _previousData); _data.guide(visitor); QMutexLocker locker(&node->getMutex()); QMetaObject::invokeMethod(node->getLinkedData(), "setAugmentedData", Q_ARG(const MetavoxelData&, _data)); } void MetavoxelSystemClient::dataChanged(const MetavoxelData& oldData) { MetavoxelClient::dataChanged(oldData); QThreadPool::globalInstance()->start(new Augmenter(_node, _data, getAugmentedData(), _remoteDataLOD)); } void MetavoxelSystemClient::sendDatagram(const QByteArray& data) { NodeList::getInstance()->writeDatagram(data, _node); Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size()); } BufferData::~BufferData() { } PointBuffer::PointBuffer(const BufferPointVector& points) : _points(points) { } void PointBuffer::render() { // initialize buffer, etc. on first render if (!_buffer.isCreated()) { _buffer.setUsagePattern(QOpenGLBuffer::StaticDraw); _buffer.create(); _buffer.bind(); _pointCount = _points.size(); _buffer.allocate(_points.constData(), _pointCount * sizeof(BufferPoint)); _points.clear(); _buffer.release(); } if (_pointCount == 0) { return; } _buffer.bind(); BufferPoint* point = 0; glVertexPointer(4, GL_FLOAT, sizeof(BufferPoint), &point->vertex); glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(BufferPoint), &point->color); glNormalPointer(GL_BYTE, sizeof(BufferPoint), &point->normal); glDrawArrays(GL_POINTS, 0, _pointCount); _buffer.release(); } HeightfieldBuffer::HeightfieldBuffer(const QByteArray& height, const QByteArray& color, const QByteArray& normal) : _height(height), _color(color), _normal(normal), _heightTexture(QOpenGLTexture::Target2D), _colorTexture(QOpenGLTexture::Target2D), _normalTexture(QOpenGLTexture::Target2D) { } void HeightfieldBuffer::render() { // initialize textures, etc. on first render if (!_heightTexture.isCreated()) { int heightSize = glm::sqrt(_height.size()); _heightTexture.setSize(heightSize, heightSize); _heightTexture.setFormat(QOpenGLTexture::LuminanceFormat); _heightTexture.allocateStorage(); _heightTexture.setData(QOpenGLTexture::Luminance, QOpenGLTexture::UInt8, _height.data()); _height.clear(); int colorSize = glm::sqrt(_color.size() / 3); _colorTexture.setSize(colorSize, colorSize); _colorTexture.setFormat(QOpenGLTexture::RGBFormat); _colorTexture.allocateStorage(); _colorTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _color.data()); _color.clear(); int normalSize = glm::sqrt(_normal.size() / 3); _normalTexture.setSize(normalSize, normalSize); _normalTexture.setFormat(QOpenGLTexture::RGBFormat); _normalTexture.allocateStorage(); _normalTexture.setData(QOpenGLTexture::BGR, QOpenGLTexture::UInt8, _normal.data()); _normal.clear(); } } BufferDataAttribute::BufferDataAttribute(const QString& name) : InlineAttribute<BufferDataPointer>(name) { } bool BufferDataAttribute::merge(void*& parent, void* children[], bool postRead) const { BufferDataPointer firstChild = decodeInline<BufferDataPointer>(children[0]); for (int i = 1; i < MERGE_COUNT; i++) { if (firstChild != decodeInline<BufferDataPointer>(children[i])) { *(BufferDataPointer*)&parent = _defaultValue; return false; } } *(BufferDataPointer*)&parent = firstChild; return true; } void DefaultMetavoxelRendererImplementation::init() { if (!_pointProgram.isLinked()) { _pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert"); _pointProgram.link(); _pointProgram.bind(); _pointScaleLocation = _pointProgram.uniformLocation("pointScale"); _pointProgram.release(); _heightfieldProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_heightfield.vert"); _heightfieldProgram.addShaderFromSourceFile(QGLShader::Fragment, Application::resourcesPath() + "shaders/metavoxel_heightfield.frag"); _heightfieldProgram.link(); } } DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() { } class PointAugmentVisitor : public MetavoxelVisitor { public: PointAugmentVisitor(const MetavoxelLOD& lod); virtual void prepare(MetavoxelData* data); virtual int visit(MetavoxelInfo& info); virtual bool postVisit(MetavoxelInfo& info); private: BufferPointVector _points; float _pointLeafSize; }; PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getColorAttribute() << AttributeRegistry::getInstance()->getNormalAttribute(), QVector<AttributePointer>() << Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod) { } const int ALPHA_RENDER_THRESHOLD = 0; void PointAugmentVisitor::prepare(MetavoxelData* data) { MetavoxelVisitor::prepare(data); const float MAX_POINT_LEAF_SIZE = 64.0f; _pointLeafSize = qMin(data->getSize(), MAX_POINT_LEAF_SIZE); } int PointAugmentVisitor::visit(MetavoxelInfo& info) { if (!info.isLeaf) { return (info.size > _pointLeafSize) ? DEFAULT_ORDER : (DEFAULT_ORDER | ALL_NODES_REST); } QRgb color = info.inputValues.at(0).getInlineValue<QRgb>(); quint8 alpha = qAlpha(color); if (alpha > ALPHA_RENDER_THRESHOLD) { QRgb normal = info.inputValues.at(1).getInlineValue<QRgb>(); BufferPoint point = { glm::vec4(info.minimum + glm::vec3(info.size, info.size, info.size) * 0.5f, info.size), { quint8(qRed(color)), quint8(qGreen(color)), quint8(qBlue(color)) }, { quint8(qRed(normal)), quint8(qGreen(normal)), quint8(qBlue(normal)) } }; _points.append(point); } if (info.size >= _pointLeafSize) { BufferPointVector swapPoints; _points.swap(swapPoints); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer( new PointBuffer(swapPoints)))); } return STOP_RECURSION; } bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) { if (info.size != _pointLeafSize) { return false; } BufferPointVector swapPoints; _points.swap(swapPoints); info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer( new PointBuffer(swapPoints)))); return true; } class HeightfieldAugmentVisitor : public MetavoxelVisitor { public: HeightfieldAugmentVisitor(const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); }; HeightfieldAugmentVisitor::HeightfieldAugmentVisitor(const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>() << Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod) { } int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) { return STOP_RECURSION; } void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous, MetavoxelInfo& info, const MetavoxelLOD& lod) { // copy the previous buffers MetavoxelData expandedPrevious = previous; while (expandedPrevious.getSize() < data.getSize()) { expandedPrevious.expand(); } const AttributePointer& pointBufferAttribute = Application::getInstance()->getMetavoxels()->getPointBufferAttribute(); MetavoxelNode* root = expandedPrevious.getRoot(pointBufferAttribute); if (root) { data.setRoot(pointBufferAttribute, root); root->incrementReferenceCount(); } PointAugmentVisitor visitor(lod); data.guideToDifferent(expandedPrevious, visitor); } class SpannerSimulateVisitor : public SpannerVisitor { public: SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod); virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); private: float _deltaTime; }; SpannerSimulateVisitor::SpannerSimulateVisitor(float deltaTime, const MetavoxelLOD& lod) : SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod), _deltaTime(deltaTime) { } bool SpannerSimulateVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) { spanner->getRenderer()->simulate(_deltaTime); return true; } void DefaultMetavoxelRendererImplementation::simulate(MetavoxelData& data, float deltaTime, MetavoxelInfo& info, const MetavoxelLOD& lod) { SpannerSimulateVisitor spannerSimulateVisitor(deltaTime, lod); data.guide(spannerSimulateVisitor); } class SpannerRenderVisitor : public SpannerVisitor { public: SpannerRenderVisitor(const MetavoxelLOD& lod); virtual bool visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize); }; SpannerRenderVisitor::SpannerRenderVisitor(const MetavoxelLOD& lod) : SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(), QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(), lod, encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) { } bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum, float clipSize) { spanner->getRenderer()->render(1.0f, SpannerRenderer::DEFAULT_MODE, clipMinimum, clipSize); return true; } class BufferRenderVisitor : public MetavoxelVisitor { public: BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod); virtual int visit(MetavoxelInfo& info); private: int _order; }; BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod) : MetavoxelVisitor(QVector<AttributePointer>() << attribute, QVector<AttributePointer>(), lod), _order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) { } int BufferRenderVisitor::visit(MetavoxelInfo& info) { BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>(); if (buffer) { buffer->render(); } return info.isLeaf ? STOP_RECURSION : _order; }