Alllmost ready with the big edge sharing rejiggery.

This commit is contained in:
Andrzej Kapolka 2014-08-14 17:10:45 -07:00
parent 62b84edc7f
commit 05d6b628fa
5 changed files with 304 additions and 184 deletions

View file

@ -37,6 +37,9 @@ void MetavoxelSystem::init() {
_pointBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(new BufferDataAttribute("pointBuffer"));
_heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
new BufferDataAttribute("heightfieldBuffer"));
_heightfieldBufferAttribute->setLODThresholdMultiplier(
AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier());
}
MetavoxelLOD MetavoxelSystem::getLOD() {
@ -382,7 +385,7 @@ float MetavoxelSystem::getHeightfieldHeight(const glm::vec3& location) {
class HeightfieldCursorRenderVisitor : public MetavoxelVisitor {
public:
HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds);
HeightfieldCursorRenderVisitor(const Box& bounds);
virtual int visit(MetavoxelInfo& info);
@ -391,9 +394,9 @@ private:
Box _bounds;
};
HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const MetavoxelLOD& lod, const Box& bounds) :
HeightfieldCursorRenderVisitor::HeightfieldCursorRenderVisitor(const Box& bounds) :
MetavoxelVisitor(QVector<AttributePointer>() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>(), lod),
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute()),
_bounds(bounds) {
}
@ -433,7 +436,7 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r
glActiveTexture(GL_TEXTURE0);
glm::vec3 extents(radius, radius, radius);
HeightfieldCursorRenderVisitor visitor(getLOD(), Box(position - extents, position + extents));
HeightfieldCursorRenderVisitor visitor(Box(position - extents, position + extents));
guideToAugmented(visitor);
DefaultMetavoxelRendererImplementation::getHeightfieldCursorProgram().release();
@ -601,11 +604,24 @@ HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,
const QByteArray& height, const QByteArray& color) :
_translation(translation),
_scale(scale),
_heightBounds(translation, translation + glm::vec3(scale, scale, scale)),
_colorBounds(_heightBounds),
_height(height),
_color(color),
_heightTextureID(0),
_colorTextureID(0),
_heightSize(glm::sqrt(height.size())) {
_heightSize(glm::sqrt(height.size())),
_heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),
_colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)),
_colorIncrement(scale / (_colorSize - SHARED_EDGE)) {
_heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER;
_heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER;
_heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
_heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
_colorBounds.maximum.x += _colorIncrement * SHARED_EDGE;
_colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;
}
HeightfieldBuffer::~HeightfieldBuffer() {
@ -807,17 +823,19 @@ BufferDataAttribute::BufferDataAttribute(const QString& 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;
*(BufferDataPointer*)&parent = _defaultValue;
for (int i = 0; i < MERGE_COUNT; i++) {
if (decodeInline<BufferDataPointer>(children[i])) {
return false;
}
}
*(BufferDataPointer*)&parent = firstChild;
return true;
}
AttributeValue BufferDataAttribute::inherit(const AttributeValue& parentValue) const {
return AttributeValue(parentValue.getAttribute());
}
void DefaultMetavoxelRendererImplementation::init() {
if (!_pointProgram.isLinked()) {
_pointProgram.addShaderFromSourceFile(QGLShader::Vertex, Application::resourcesPath() + "shaders/metavoxel_point.vert");
@ -923,206 +941,279 @@ bool PointAugmentVisitor::postVisit(MetavoxelInfo& info) {
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) {
}
class BorderFetchVisitor : public MetavoxelVisitor {
class HeightfieldFetchVisitor : public MetavoxelVisitor {
public:
BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer);
HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
void init(HeightfieldBuffer* buffer) { _buffer = buffer; }
virtual int visit(MetavoxelInfo& info);
private:
const QVector<Box>& _intersections;
HeightfieldBuffer* _buffer;
Box _expandedBounds;
int _heightSize;
float _heightExtension;
int _colorSize;
float _colorExtension;
Box _colorBounds;
};
BorderFetchVisitor::BorderFetchVisitor(const MetavoxelLOD& lod, HeightfieldBuffer* buffer) :
HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod),
_buffer(buffer),
_expandedBounds(_buffer->getTranslation(), _buffer->getTranslation() +
glm::vec3(_buffer->getScale(), _buffer->getScale(), _buffer->getScale())),
_heightSize(glm::sqrt(buffer->getHeight().size())),
_heightExtension(_buffer->getScale() / (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)),
_colorSize(glm::sqrt(buffer->getColor().size() / HeightfieldData::COLOR_BYTES)),
_colorBounds(_expandedBounds) {
_expandedBounds.minimum.x -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER;
_expandedBounds.minimum.z -= _heightExtension * HeightfieldBuffer::HEIGHT_BORDER;
_expandedBounds.maximum.x += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE);
_expandedBounds.maximum.z += _heightExtension * (HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE);
if (_colorSize > 0) {
_colorExtension = buffer->getScale() / (_colorSize - HeightfieldBuffer::SHARED_EDGE);
_colorBounds.maximum.x += _colorExtension * HeightfieldBuffer::SHARED_EDGE;
_colorBounds.maximum.z += _colorExtension * HeightfieldBuffer::SHARED_EDGE;
}
_intersections(intersections) {
}
int BorderFetchVisitor::visit(MetavoxelInfo& info) {
int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
Box bounds = info.getBounds();
if (!bounds.intersects(_expandedBounds)) {
const Box& heightBounds = _buffer->getHeightBounds();
if (!bounds.intersects(heightBounds)) {
return STOP_RECURSION;
}
if (!info.isLeaf && info.size > _buffer->getScale()) {
return DEFAULT_ORDER;
}
if (_expandedBounds.contains(bounds)) {
return STOP_RECURSION; // this is the principal, which we've already filled in
}
HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (!height) {
return STOP_RECURSION;
}
Box intersection = bounds.getIntersection(_expandedBounds);
int destX = glm::round((intersection.minimum.x - _expandedBounds.minimum.x) / _heightExtension);
int destY = glm::round((intersection.minimum.z - _expandedBounds.minimum.z) / _heightExtension);
int destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _heightExtension);
int destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _heightExtension);
char* dest = _buffer->getHeight().data() + destY * _heightSize + destX;
const QByteArray& srcHeight = height->getContents();
int srcSize = glm::sqrt(srcHeight.size());
float srcExtension = info.size / srcSize;
if (info.size == _buffer->getScale() && srcSize == (_heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) {
// easy case: same resolution
int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension);
int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension);
foreach (const Box& intersection, _intersections) {
Box overlap = intersection.getIntersection(bounds);
if (overlap.isEmpty()) {
continue;
}
float heightIncrement = _buffer->getHeightIncrement();
int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement;
int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement;
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement);
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement);
int heightSize = _buffer->getHeightSize();
char* dest = _buffer->getHeight().data() + destY * heightSize + destX;
const char* src = srcHeight.constData() + srcY * srcSize + srcX;
for (int y = 0; y < destHeight; y++, src += srcSize, dest += _heightSize) {
memcpy(dest, src, destWidth);
const QByteArray& srcHeight = height->getContents();
int srcSize = glm::sqrt(srcHeight.size());
float srcIncrement = info.size / srcSize;
if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) {
// easy case: same resolution
int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
const char* src = srcHeight.constData() + srcY * srcSize + srcX;
for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) {
memcpy(dest, src, destWidth);
}
} else {
// more difficult: different resolutions
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
float srcAdvance = heightIncrement / srcIncrement;
int shift = 0;
float size = _buffer->getScale();
while (size < info.size) {
shift++;
size *= 2.0f;
}
const int EIGHT_BIT_MAXIMUM = 255;
int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale();
for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) {
const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize;
float lineSrcX = srcX;
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
*lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM);
}
}
}
} else {
// more difficult: different resolutions
float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension;
float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension;
float srcIncrement = _heightExtension / srcExtension;
int shift = 0;
float size = _buffer->getScale();
while (size < info.size) {
shift++;
size *= 2.0f;
int colorSize = _buffer->getColorSize();
if (colorSize == 0) {
return STOP_RECURSION;
}
const int EIGHT_BIT_MAXIMUM = 255;
int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale();
for (int y = 0; y < destHeight; y++, dest += _heightSize, srcY += srcIncrement) {
const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize;
float lineSrcX = srcX;
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcIncrement) {
*lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM);
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
if (!color) {
return STOP_RECURSION;
}
const Box& colorBounds = _buffer->getColorBounds();
overlap = colorBounds.getIntersection(overlap);
float colorIncrement = _buffer->getColorIncrement();
destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement;
destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement;
destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement);
destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement);
dest = _buffer->getColor().data() + (destY * colorSize + destX) * HeightfieldData::COLOR_BYTES;
int destStride = colorSize * HeightfieldData::COLOR_BYTES;
int destBytes = destWidth * HeightfieldData::COLOR_BYTES;
const QByteArray& srcColor = color->getContents();
srcSize = glm::sqrt(srcColor.size() / HeightfieldData::COLOR_BYTES);
int srcStride = srcSize * HeightfieldData::COLOR_BYTES;
srcIncrement = info.size / srcSize;
if (srcIncrement == colorIncrement) {
// easy case: same resolution
int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
const char* src = srcColor.constData() + (srcY * srcSize + srcX) * HeightfieldData::COLOR_BYTES;
for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {
memcpy(dest, src, destBytes);
}
} else {
// more difficult: different resolutions
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
float srcAdvance = colorIncrement / srcIncrement;
for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) {
const char* src = srcColor.constData() + (int)srcY * srcStride;
float lineSrcX = srcX;
for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += HeightfieldData::COLOR_BYTES,
lineSrcX += srcAdvance) {
const char* lineSrc = src + (int)lineSrcX * HeightfieldData::COLOR_BYTES;
lineDest[0] = lineSrc[0];
lineDest[1] = lineSrc[1];
lineDest[2] = lineSrc[2];
}
}
}
}
if (_colorSize == 0) {
return STOP_RECURSION;
}
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
if (!color) {
return STOP_RECURSION;
}
intersection = bounds.getIntersection(_colorBounds);
destX = glm::round((intersection.minimum.x - _colorBounds.minimum.x) / _colorExtension);
destY = glm::round((intersection.minimum.z - _colorBounds.minimum.z) / _colorExtension);
destWidth = glm::round((intersection.maximum.x - intersection.minimum.x) / _colorExtension);
destHeight = glm::round((intersection.maximum.z - intersection.minimum.z) / _colorExtension);
dest = _buffer->getColor().data() + (destY * _colorSize + destX) * HeightfieldData::COLOR_BYTES;
int destStride = _colorSize * HeightfieldData::COLOR_BYTES;
int destBytes = destWidth * HeightfieldData::COLOR_BYTES;
const QByteArray& srcColor = color->getContents();
srcSize = glm::sqrt(srcColor.size() / HeightfieldData::COLOR_BYTES);
int srcStride = srcSize * HeightfieldData::COLOR_BYTES;
srcExtension = info.size / srcSize;
if (srcExtension == _colorExtension) {
// easy case: same resolution
int srcX = glm::round((intersection.minimum.x - info.minimum.x) / srcExtension);
int srcY = glm::round((intersection.minimum.z - info.minimum.z) / srcExtension);
const char* src = srcColor.constData() + (srcY * srcSize + srcX) * HeightfieldData::COLOR_BYTES;
for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {
memcpy(dest, src, destBytes);
}
} else {
// more difficult: different resolutions
float srcX = (intersection.minimum.x - info.minimum.x) / srcExtension;
float srcY = (intersection.minimum.z - info.minimum.z) / srcExtension;
float srcIncrement = _colorExtension / srcExtension;
for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcIncrement) {
const char* src = srcColor.constData() + (int)srcY * srcStride;
float lineSrcX = srcX;
for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += HeightfieldData::COLOR_BYTES,
lineSrcX += srcIncrement) {
const char* lineSrc = src + (int)lineSrcX * HeightfieldData::COLOR_BYTES;
lineDest[0] = lineSrc[0];
lineDest[1] = lineSrc[1];
lineDest[2] = lineSrc[2];
}
}
}
return STOP_RECURSION;
}
int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) {
if (info.isLeaf) {
HeightfieldBuffer* buffer = NULL;
HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (height) {
const QByteArray& heightContents = height->getContents();
int size = glm::sqrt(heightContents.size());
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
QByteArray extendedHeightContents(extendedSize * extendedSize, 0);
char* dest = extendedHeightContents.data() + (extendedSize + 1) * HeightfieldBuffer::HEIGHT_BORDER;
const char* src = heightContents.constData();
for (int z = 0; z < size; z++, src += size, dest += extendedSize) {
memcpy(dest, src, size);
}
QByteArray extendedColorContents;
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
if (color) {
const QByteArray& colorContents = color->getContents();
int colorSize = glm::sqrt(colorContents.size() / HeightfieldData::COLOR_BYTES);
int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE;
extendedColorContents = QByteArray(extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES, 0);
char* dest = extendedColorContents.data();
const char* src = colorContents.constData();
int srcStride = colorSize * HeightfieldData::COLOR_BYTES;
int destStride = extendedColorSize * HeightfieldData::COLOR_BYTES;
for (int z = 0; z < colorSize; z++, src += srcStride, dest += destStride) {
memcpy(dest, src, srcStride);
}
}
buffer = new HeightfieldBuffer(info.minimum, info.size, extendedHeightContents, extendedColorContents);
BorderFetchVisitor visitor(_lod, buffer);
_data->guide(visitor);
class HeightfieldRegionVisitor : public MetavoxelVisitor {
public:
QVector<Box> regions;
Box regionBounds;
HeightfieldRegionVisitor(const MetavoxelLOD& lod);
virtual int visit(MetavoxelInfo& info);
private:
void addRegion(const Box& unextended, const Box& extended);
QVector<Box> _intersections;
HeightfieldFetchVisitor _fetchVisitor;
};
HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)),
_fetchVisitor(lod, _intersections) {
}
int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
if (!info.isLeaf) {
return DEFAULT_ORDER;
}
HeightfieldBuffer* buffer = NULL;
HeightfieldDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldDataPointer>();
if (height) {
const QByteArray& heightContents = height->getContents();
int size = glm::sqrt(heightContents.size());
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
int heightContentsSize = extendedSize * extendedSize;
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
int colorContentsSize = 0;
if (color) {
const QByteArray& colorContents = color->getContents();
int colorSize = glm::sqrt(colorContents.size() / HeightfieldData::COLOR_BYTES);
int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE;
colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES;
}
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer)));
const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(
info.inputValues.at(2).getInlineValue<BufferDataPointer>().data());
Box bounds = info.getBounds();
if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&
existingBuffer->getColor().size() == colorContentsSize) {
// we already have a buffer of the correct resolution
addRegion(bounds, existingBuffer->getHeightBounds());
return STOP_RECURSION;
}
// we must create a new buffer and update its borders
buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0),
QByteArray(colorContentsSize, 0));
const Box& heightBounds = buffer->getHeightBounds();
addRegion(bounds, heightBounds);
_intersections.clear();
_intersections.append(Box(heightBounds.minimum,
glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z)));
_intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z),
glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z)));
_intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z),
heightBounds.maximum));
_intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z),
glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z)));
_fetchVisitor.init(buffer);
_data->guide(_fetchVisitor);
}
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(buffer)));
return STOP_RECURSION;
}
void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
regions.append(unextended);
regionBounds.add(extended);
}
class HeightfieldUpdateVisitor : public MetavoxelVisitor {
public:
HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds);
virtual int visit(MetavoxelInfo& info);
private:
const QVector<Box>& _regions;
const Box& _regionBounds;
QVector<Box> _intersections;
HeightfieldFetchVisitor _fetchVisitor;
};
HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions,
const Box& regionBounds) :
MetavoxelVisitor(QVector<AttributePointer>() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
_regions(regions),
_regionBounds(regionBounds),
_fetchVisitor(lod, _intersections) {
}
int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {
if (!info.getBounds().intersects(_regionBounds)) {
return STOP_RECURSION;
}
return DEFAULT_ORDER;
if (!info.isLeaf) {
return DEFAULT_ORDER;
}
const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>(
info.inputValues.at(0).getInlineValue<BufferDataPointer>().data());
if (!buffer) {
return STOP_RECURSION;
}
_intersections.clear();
foreach (const Box& region, _regions) {
if (region.intersects(buffer->getHeightBounds())) {
_intersections.append(region.getIntersection(buffer->getHeightBounds()));
}
}
if (_intersections.isEmpty()) {
return STOP_RECURSION;
}
HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,
buffer->getHeight(), buffer->getColor());
_fetchVisitor.init(newBuffer);
_data->guide(_fetchVisitor);
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer)));
return STOP_RECURSION;
}
void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const MetavoxelData& previous,
@ -1149,8 +1240,12 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const
PointAugmentVisitor pointAugmentVisitor(lod);
data.guideToDifferent(expandedPrevious, pointAugmentVisitor);
HeightfieldAugmentVisitor heightfieldAugmentVisitor(lod);
data.guideToDifferent(expandedPrevious, heightfieldAugmentVisitor);
HeightfieldRegionVisitor heightfieldRegionVisitor(lod);
data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor);
HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions,
heightfieldRegionVisitor.regionBounds);
data.guide(heightfieldUpdateVisitor);
}
class SpannerSimulateVisitor : public SpannerVisitor {
@ -1222,7 +1317,7 @@ bool SpannerRenderVisitor::visit(Spanner* spanner, const glm::vec3& clipMinimum,
class BufferRenderVisitor : public MetavoxelVisitor {
public:
BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod);
BufferRenderVisitor(const AttributePointer& attribute);
virtual int visit(MetavoxelInfo& info);
@ -1232,8 +1327,8 @@ private:
int _containmentDepth;
};
BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute, const MetavoxelLOD& lod) :
MetavoxelVisitor(QVector<AttributePointer>() << attribute, QVector<AttributePointer>(), lod),
BufferRenderVisitor::BufferRenderVisitor(const AttributePointer& attribute) :
MetavoxelVisitor(QVector<AttributePointer>() << attribute),
_order(encodeOrder(Application::getInstance()->getViewFrustum()->getDirection())),
_containmentDepth(INT_MAX) {
}
@ -1247,11 +1342,14 @@ int BufferRenderVisitor::visit(MetavoxelInfo& info) {
}
_containmentDepth = (intersection == Frustum::CONTAINS_INTERSECTION) ? _depth : INT_MAX;
}
if (!info.isLeaf) {
return _order;
}
BufferDataPointer buffer = info.inputValues.at(0).getInlineValue<BufferDataPointer>();
if (buffer) {
buffer->render();
}
return info.isLeaf ? STOP_RECURSION : _order;
return STOP_RECURSION;
}
void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, MetavoxelInfo& info, const MetavoxelLOD& lod) {
@ -1280,7 +1378,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
glDisable(GL_BLEND);
BufferRenderVisitor pointRenderVisitor(Application::getInstance()->getMetavoxels()->getPointBufferAttribute(), lod);
BufferRenderVisitor pointRenderVisitor(Application::getInstance()->getMetavoxels()->getPointBufferAttribute());
data.guide(pointRenderVisitor);
glDisable(GL_VERTEX_PROGRAM_POINT_SIZE_ARB);
@ -1300,8 +1398,7 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(),
lod);
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
data.guide(heightfieldRenderVisitor);
_heightfieldProgram.release();

View file

@ -145,6 +145,9 @@ public:
const glm::vec3& getTranslation() const { return _translation; }
float getScale() const { return _scale; }
const Box& getHeightBounds() const { return _heightBounds; }
const Box& getColorBounds() const { return _colorBounds; }
QByteArray& getHeight() { return _height; }
const QByteArray& getHeight() const { return _height; }
@ -154,17 +157,28 @@ public:
QByteArray getUnextendedHeight() const;
QByteArray getUnextendedColor() const;
int getHeightSize() const { return _heightSize; }
float getHeightIncrement() const { return _heightIncrement; }
int getColorSize() const { return _colorSize; }
float getColorIncrement() const { return _colorIncrement; }
virtual void render(bool cursor = false);
private:
glm::vec3 _translation;
float _scale;
Box _heightBounds;
Box _colorBounds;
QByteArray _height;
QByteArray _color;
GLuint _heightTextureID;
GLuint _colorTextureID;
int _heightSize;
float _heightIncrement;
int _colorSize;
float _colorIncrement;
typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair;
static QHash<int, BufferPair> _bufferPairs;
@ -193,6 +207,8 @@ public:
Q_INVOKABLE BufferDataAttribute(const QString& name = QString());
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
};
/// Renders metavoxels as points.

View file

@ -55,7 +55,7 @@ AttributeRegistry::AttributeRegistry() :
const float SPANNER_LOD_THRESHOLD_MULTIPLIER = 8.0f;
_spannersAttribute->setLODThresholdMultiplier(SPANNER_LOD_THRESHOLD_MULTIPLIER);
const float HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER = 32.0f;
const float HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER = 40.0f;
_heightfieldAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
_heightfieldColorAttribute->setLODThresholdMultiplier(HEIGHTFIELD_LOD_THRESHOLD_MULTIPLIER);
}

View file

@ -164,6 +164,11 @@ Box::Box(const glm::vec3& minimum, const glm::vec3& maximum) :
minimum(minimum), maximum(maximum) {
}
void Box::add(const Box& other) {
minimum = glm::min(minimum, other.minimum);
maximum = glm::max(maximum, other.maximum);
}
bool Box::contains(const glm::vec3& point) const {
return point.x >= minimum.x && point.x <= maximum.x &&
point.y >= minimum.y && point.y <= maximum.y &&

View file

@ -44,6 +44,8 @@ public:
explicit Box(const glm::vec3& minimum = glm::vec3(), const glm::vec3& maximum = glm::vec3());
void add(const Box& other);
bool contains(const glm::vec3& point) const;
bool contains(const Box& other) const;