mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 03:53:10 +02:00
Simpler rendering.
This commit is contained in:
parent
4f5448f529
commit
e05884d4a3
4 changed files with 108 additions and 123 deletions
|
@ -90,8 +90,8 @@ public:
|
|||
|
||||
SpannerRenderVisitor::SpannerRenderVisitor() :
|
||||
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||
QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannerMaskAttribute(),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), Application::getInstance()->getMetavoxels()->getLOD(),
|
||||
QVector<AttributePointer>(), QVector<AttributePointer>(), QVector<AttributePointer>(),
|
||||
Application::getInstance()->getMetavoxels()->getLOD(),
|
||||
encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())) {
|
||||
}
|
||||
|
||||
|
@ -239,53 +239,22 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {
|
|||
Application::getInstance()->getBandwidthMeter()->outputStream(BandwidthMeter::METAVOXELS).updateValue(data.size());
|
||||
}
|
||||
|
||||
PointBuffer::PointBuffer(const QVector<BufferPointVectorPair>& levelPoints) :
|
||||
_levelPoints(levelPoints) {
|
||||
PointBuffer::PointBuffer(const BufferPointVector& points) :
|
||||
_points(points) {
|
||||
}
|
||||
|
||||
void PointBuffer::render(int level) {
|
||||
void PointBuffer::render() {
|
||||
// initalize buffer, etc. on first render
|
||||
if (!_buffer.isCreated()) {
|
||||
_offsets.append(0);
|
||||
_lastLeafCount = 0;
|
||||
int totalPoints = 0;
|
||||
foreach (const BufferPointVectorPair& pair, _levelPoints) {
|
||||
_offsets.append(totalPoints += ((_lastLeafCount += pair.first.size()) + pair.second.size()));
|
||||
}
|
||||
_buffer.setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||
_buffer.create();
|
||||
_buffer.bind();
|
||||
_buffer.allocate(totalPoints * sizeof(BufferPoint));
|
||||
int offset = 0;
|
||||
for (int i = 0; i < _levelPoints.size(); i++) {
|
||||
// write the internal nodes from the current level
|
||||
const BufferPointVector& internal = _levelPoints.at(i).second;
|
||||
int length = internal.size() * sizeof(BufferPoint);
|
||||
_buffer.write(offset, internal.constData(), length);
|
||||
offset += length;
|
||||
|
||||
// and the leaves from the top down
|
||||
for (int j = 0; j <= i; j++) {
|
||||
const BufferPointVector& leaves = _levelPoints.at(j).first;
|
||||
length = leaves.size() * sizeof(BufferPoint);
|
||||
_buffer.write(offset, leaves.constData(), length);
|
||||
offset += length;
|
||||
}
|
||||
}
|
||||
_levelPoints.clear();
|
||||
_pointCount = _points.size();
|
||||
_buffer.allocate(_points.constData(), _pointCount * sizeof(BufferPoint));
|
||||
_points.clear();
|
||||
_buffer.release();
|
||||
}
|
||||
int first, count;
|
||||
int nextLevel = level + 1;
|
||||
if (nextLevel >= _offsets.size()) {
|
||||
first = _offsets.last() - _lastLeafCount;
|
||||
count = _lastLeafCount;
|
||||
|
||||
} else {
|
||||
first = _offsets.at(level);
|
||||
count = _offsets.at(nextLevel) - first;
|
||||
}
|
||||
if (count == 0) {
|
||||
if (_pointCount == 0) {
|
||||
return;
|
||||
}
|
||||
_buffer.bind();
|
||||
|
@ -295,7 +264,7 @@ void PointBuffer::render(int level) {
|
|||
glColorPointer(3, GL_UNSIGNED_BYTE, sizeof(BufferPoint), &point->color);
|
||||
glNormalPointer(GL_BYTE, sizeof(BufferPoint), &point->normal);
|
||||
|
||||
glDrawArrays(GL_POINTS, first, count);
|
||||
glDrawArrays(GL_POINTS, 0, _pointCount);
|
||||
|
||||
_buffer.release();
|
||||
}
|
||||
|
@ -304,23 +273,18 @@ PointBufferAttribute::PointBufferAttribute() :
|
|||
InlineAttribute<PointBufferPointer>("pointBuffer") {
|
||||
}
|
||||
|
||||
MetavoxelNode* PointBufferAttribute::createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const {
|
||||
return new MetavoxelNode(value, original);
|
||||
}
|
||||
|
||||
bool PointBufferAttribute::merge(void*& parent, void* children[], bool postRead) const {
|
||||
for (int i = 0; i < MERGE_COUNT; i++) {
|
||||
if (decodeInline<PointBufferPointer>(children[i])) {
|
||||
PointBufferPointer firstChild = decodeInline<PointBufferPointer>(children[0]);
|
||||
for (int i = 1; i < MERGE_COUNT; i++) {
|
||||
if (firstChild != decodeInline<PointBufferPointer>(children[i])) {
|
||||
*(PointBufferPointer*)&parent = _defaultValue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
*(PointBufferPointer*)&parent = firstChild;
|
||||
return true;
|
||||
}
|
||||
|
||||
AttributeValue PointBufferAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
void PointMetavoxelRendererImplementation::init() {
|
||||
if (!_program.isLinked()) {
|
||||
_program.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert");
|
||||
|
@ -340,12 +304,14 @@ public:
|
|||
|
||||
PointAugmentVisitor(const MetavoxelLOD& lod);
|
||||
|
||||
virtual void prepare(MetavoxelData* data);
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
QVector<BufferPointVectorPair> _depthPoints;
|
||||
BufferPointVector _points;
|
||||
float _pointLeafSize;
|
||||
};
|
||||
|
||||
PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& lod) :
|
||||
|
@ -356,48 +322,61 @@ PointAugmentVisitor::PointAugmentVisitor(const MetavoxelLOD& 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 (_depth >= _depthPoints.size()) {
|
||||
_depthPoints.resize(_depth + 1);
|
||||
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) {
|
||||
return info.isLeaf ? STOP_RECURSION : (DEFAULT_ORDER | ALL_NODES);
|
||||
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);
|
||||
}
|
||||
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)) } };
|
||||
if (info.isLeaf) {
|
||||
_depthPoints[_depth].first.append(point);
|
||||
return STOP_RECURSION;
|
||||
if (info.size >= _pointLeafSize) {
|
||||
BufferPointVector swapPoints;
|
||||
_points.swap(swapPoints);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(PointBufferPointer(
|
||||
new PointBuffer(swapPoints))));
|
||||
}
|
||||
_depthPoints[_depth].second.append(point);
|
||||
return DEFAULT_ORDER | ALL_NODES;
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) {
|
||||
if (_depth != 0) {
|
||||
if (info.size != _pointLeafSize) {
|
||||
return false;
|
||||
}
|
||||
int lastDepth = _depthPoints.size();
|
||||
QVector<BufferPointVectorPair> levelPoints(lastDepth - _depth);
|
||||
for (int i = 0; i < levelPoints.size(); i++) {
|
||||
BufferPointVectorPair& levelPair = levelPoints[i];
|
||||
BufferPointVectorPair& depthPair = _depthPoints[_depth + i];
|
||||
levelPair.first.swap(depthPair.first);
|
||||
levelPair.second.swap(depthPair.second);
|
||||
}
|
||||
BufferPointVector swapPoints;
|
||||
_points.swap(swapPoints);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(PointBufferPointer(
|
||||
new PointBuffer(levelPoints))));
|
||||
new PointBuffer(swapPoints))));
|
||||
return true;
|
||||
}
|
||||
|
||||
void PointMetavoxelRendererImplementation::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(previous, visitor, &info);
|
||||
data.guideToDifferent(expandedPrevious, visitor);
|
||||
}
|
||||
|
||||
class PointRenderVisitor : public MetavoxelVisitor {
|
||||
|
@ -421,7 +400,7 @@ PointRenderVisitor::PointRenderVisitor(const MetavoxelLOD& lod) :
|
|||
int PointRenderVisitor::visit(MetavoxelInfo& info) {
|
||||
PointBufferPointer buffer = info.inputValues.at(0).getInlineValue<PointBufferPointer>();
|
||||
if (buffer) {
|
||||
buffer->render(1000);
|
||||
buffer->render();
|
||||
}
|
||||
return info.isLeaf ? STOP_RECURSION : _order;
|
||||
}
|
||||
|
@ -450,7 +429,7 @@ void PointMetavoxelRendererImplementation::render(MetavoxelData& data, Metavoxel
|
|||
glDisable(GL_BLEND);
|
||||
|
||||
PointRenderVisitor visitor(lod);
|
||||
data.guide(visitor, &info);
|
||||
data.guide(visitor);
|
||||
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
|
|
|
@ -23,12 +23,8 @@
|
|||
|
||||
#include "renderer/ProgramObject.h"
|
||||
|
||||
class BufferPoint;
|
||||
class Model;
|
||||
|
||||
typedef QVector<BufferPoint> BufferPointVector;
|
||||
typedef QPair<BufferPointVector, BufferPointVector> BufferPointVectorPair;
|
||||
|
||||
/// Renders a metavoxel tree.
|
||||
class MetavoxelSystem : public MetavoxelClientManager {
|
||||
Q_OBJECT
|
||||
|
@ -66,6 +62,8 @@ public:
|
|||
quint8 normal[3];
|
||||
};
|
||||
|
||||
typedef QVector<BufferPoint> BufferPointVector;
|
||||
|
||||
Q_DECLARE_METATYPE(BufferPointVector)
|
||||
|
||||
/// A client session associated with a single server.
|
||||
|
@ -94,20 +92,19 @@ private:
|
|||
QReadWriteLock _augmentedDataLock;
|
||||
};
|
||||
|
||||
/// Contains the information necessary to render a group of points at variable detail levels.
|
||||
/// Contains the information necessary to render a group of points.
|
||||
class PointBuffer : public QSharedData {
|
||||
public:
|
||||
|
||||
PointBuffer(const QVector<BufferPointVectorPair>& levelPoints);
|
||||
PointBuffer(const BufferPointVector& points);
|
||||
|
||||
void render(int level);
|
||||
void render();
|
||||
|
||||
private:
|
||||
|
||||
QVector<BufferPointVectorPair> _levelPoints;
|
||||
BufferPointVector _points;
|
||||
QOpenGLBuffer _buffer;
|
||||
QVector<int> _offsets;
|
||||
int _lastLeafCount;
|
||||
int _pointCount;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<PointBuffer> PointBufferPointer;
|
||||
|
@ -120,9 +117,7 @@ public:
|
|||
|
||||
Q_INVOKABLE PointBufferAttribute();
|
||||
|
||||
virtual MetavoxelNode* createMetavoxelNode(const AttributeValue& value, const MetavoxelNode* original) const;
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
/// Renders metavoxels as points.
|
||||
|
|
|
@ -81,7 +81,7 @@ Box MetavoxelData::getBounds() const {
|
|||
return Box(glm::vec3(-halfSize, -halfSize, -halfSize), glm::vec3(halfSize, halfSize, halfSize));
|
||||
}
|
||||
|
||||
void MetavoxelData::guide(MetavoxelVisitor& visitor, const MetavoxelInfo* start) {
|
||||
void MetavoxelData::guide(MetavoxelVisitor& visitor) {
|
||||
// let the visitor know we're about to begin a tour
|
||||
visitor.prepare(this);
|
||||
|
||||
|
@ -128,7 +128,7 @@ void MetavoxelData::guide(MetavoxelVisitor& visitor, const MetavoxelInfo* start)
|
|||
visitor.releaseVisitation();
|
||||
}
|
||||
|
||||
void MetavoxelData::guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor, const MetavoxelInfo* start) {
|
||||
void MetavoxelData::guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor) {
|
||||
// if the other data is smaller, we need to expand it to compare
|
||||
const MetavoxelData* expandedOther = &other;
|
||||
if (_size > other._size) {
|
||||
|
@ -1249,6 +1249,7 @@ const int MetavoxelVisitor::DEFAULT_ORDER = encodeOrder(0, 1, 2, 3, 4, 5, 6, 7);
|
|||
const int MetavoxelVisitor::STOP_RECURSION = 0;
|
||||
const int MetavoxelVisitor::SHORT_CIRCUIT = -1;
|
||||
const int MetavoxelVisitor::ALL_NODES = 1 << 24;
|
||||
const int MetavoxelVisitor::ALL_NODES_REST = 1 << 25;
|
||||
|
||||
MetavoxelVisitor::MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs, const MetavoxelLOD& lod) :
|
||||
|
@ -1428,32 +1429,7 @@ bool MetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) {
|
|||
DefaultMetavoxelGuide::DefaultMetavoxelGuide() {
|
||||
}
|
||||
|
||||
bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
// save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute
|
||||
float lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) *
|
||||
visitation.visitor->getLOD().threshold;
|
||||
visitation.info.isLODLeaf = (visitation.info.size < lodBase * visitation.visitor->getMinimumLODThresholdMultiplier());
|
||||
visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves();
|
||||
int encodedOrder = visitation.visitor->visit(visitation.info);
|
||||
if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < visitation.outputNodes.size(); i++) {
|
||||
OwnedAttributeValue& value = visitation.info.outputValues[i];
|
||||
if (!value.getAttribute()) {
|
||||
continue;
|
||||
}
|
||||
MetavoxelNode*& node = visitation.outputNodes[i];
|
||||
if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) {
|
||||
// "set" to same value; disregard
|
||||
value = AttributeValue();
|
||||
} else {
|
||||
node = value.getAttribute()->createMetavoxelNode(value, node);
|
||||
}
|
||||
}
|
||||
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
|
||||
return true;
|
||||
}
|
||||
static inline bool defaultGuideToChildren(MetavoxelVisitation& visitation, float lodBase, int encodedOrder) {
|
||||
MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation();
|
||||
nextVisitation.info.size = visitation.info.size * 0.5f;
|
||||
for (int i = 0; i < MetavoxelNode::CHILD_COUNT; i++) {
|
||||
|
@ -1546,6 +1522,35 @@ bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
|||
return true;
|
||||
}
|
||||
|
||||
bool DefaultMetavoxelGuide::guide(MetavoxelVisitation& visitation) {
|
||||
// save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute
|
||||
float lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) *
|
||||
visitation.visitor->getLOD().threshold;
|
||||
visitation.info.isLODLeaf = (visitation.info.size < lodBase * visitation.visitor->getMinimumLODThresholdMultiplier());
|
||||
visitation.info.isLeaf = visitation.info.isLODLeaf || visitation.allInputNodesLeaves();
|
||||
int encodedOrder = visitation.visitor->visit(visitation.info);
|
||||
if (encodedOrder == MetavoxelVisitor::SHORT_CIRCUIT) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < visitation.outputNodes.size(); i++) {
|
||||
OwnedAttributeValue& value = visitation.info.outputValues[i];
|
||||
if (!value.getAttribute()) {
|
||||
continue;
|
||||
}
|
||||
MetavoxelNode*& node = visitation.outputNodes[i];
|
||||
if (node && node->isLeaf() && value.getAttribute()->equal(value.getValue(), node->getAttributeValue())) {
|
||||
// "set" to same value; disregard
|
||||
value = AttributeValue();
|
||||
} else {
|
||||
node = value.getAttribute()->createMetavoxelNode(value, node);
|
||||
}
|
||||
}
|
||||
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
|
||||
return true;
|
||||
}
|
||||
return (encodedOrder == MetavoxelVisitor::STOP_RECURSION || defaultGuideToChildren(visitation, lodBase, encodedOrder));
|
||||
}
|
||||
|
||||
bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) {
|
||||
// save the core of the LOD calculation; we'll reuse it to determine whether to subdivide each attribute
|
||||
float lodBase = glm::distance(visitation.visitor->getLOD().position, visitation.info.getCenter()) *
|
||||
|
@ -1572,6 +1577,9 @@ bool DefaultMetavoxelGuide::guideToDifferent(MetavoxelVisitation& visitation) {
|
|||
if (encodedOrder == MetavoxelVisitor::STOP_RECURSION) {
|
||||
return true;
|
||||
}
|
||||
if (encodedOrder & MetavoxelVisitor::ALL_NODES_REST) {
|
||||
return defaultGuideToChildren(visitation, lodBase, encodedOrder);
|
||||
}
|
||||
bool onlyVisitDifferent = !(encodedOrder & MetavoxelVisitor::ALL_NODES);
|
||||
MetavoxelVisitation& nextVisitation = visitation.visitor->acquireVisitation();
|
||||
nextVisitation.compareNodes.resize(visitation.compareNodes.size());
|
||||
|
|
|
@ -81,12 +81,10 @@ public:
|
|||
Box getBounds() const;
|
||||
|
||||
/// Applies the specified visitor to the contained voxels.
|
||||
/// \param start the location at which to start, or NULL for the root
|
||||
void guide(MetavoxelVisitor& visitor, const MetavoxelInfo* start = NULL);
|
||||
void guide(MetavoxelVisitor& visitor);
|
||||
|
||||
/// Guides the specified visitor to the voxels that differ from those of the specified other.
|
||||
/// \param start the location at which to start, or NULL for the root
|
||||
void guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor, const MetavoxelInfo* start = NULL);
|
||||
void guideToDifferent(const MetavoxelData& other, MetavoxelVisitor& visitor);
|
||||
|
||||
/// Inserts a spanner into the specified attribute layer.
|
||||
void insert(const AttributePointer& attribute, const SharedObjectPointer& object);
|
||||
|
@ -296,9 +294,14 @@ public:
|
|||
/// A special "order" that short-circuits the tour.
|
||||
static const int SHORT_CIRCUIT;
|
||||
|
||||
/// A flag combined with an order that instructs us to return to visiting all nodes (rather than the different ones).
|
||||
/// A flag combined with an order that instructs us to return to visiting all nodes (rather than the different ones) for
|
||||
/// just this level.
|
||||
static const int ALL_NODES;
|
||||
|
||||
/// A flag combined with an order that instructs us to return to visiting all nodes (rather than the different ones) for
|
||||
/// this level and all beneath it.
|
||||
static const int ALL_NODES_REST;
|
||||
|
||||
MetavoxelVisitor(const QVector<AttributePointer>& inputs,
|
||||
const QVector<AttributePointer>& outputs = QVector<AttributePointer>(),
|
||||
const MetavoxelLOD& lod = MetavoxelLOD());
|
||||
|
|
Loading…
Reference in a new issue