mirror of
https://github.com/overte-org/overte.git
synced 2025-04-26 05:56:38 +02:00
More progress towards allowing different resolutions for height and color,
material, etc.
This commit is contained in:
parent
32781d53a2
commit
d28da9250f
5 changed files with 281 additions and 150 deletions
|
@ -1006,16 +1006,14 @@ QByteArray HeightfieldBuffer::getUnextendedHeight() const {
|
||||||
return unextended;
|
return unextended;
|
||||||
}
|
}
|
||||||
|
|
||||||
QByteArray HeightfieldBuffer::getUnextendedColor() const {
|
QByteArray HeightfieldBuffer::getUnextendedColor(int x, int y) const {
|
||||||
int srcSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES));
|
int unextendedSize = _heightSize - HEIGHT_EXTENSION;
|
||||||
int destSize = srcSize - 1;
|
QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0);
|
||||||
QByteArray unextended(destSize * destSize * DataBlock::COLOR_BYTES, 0);
|
|
||||||
const char* src = _color.constData();
|
|
||||||
int srcStride = srcSize * DataBlock::COLOR_BYTES;
|
|
||||||
char* dest = unextended.data();
|
char* dest = unextended.data();
|
||||||
int destStride = destSize * DataBlock::COLOR_BYTES;
|
const char* src = _color.constData() + (y * _colorSize + x) * unextendedSize * DataBlock::COLOR_BYTES;
|
||||||
for (int z = 0; z < destSize; z++, src += srcStride, dest += destStride) {
|
for (int z = 0; z < unextendedSize; z++, dest += unextendedSize * DataBlock::COLOR_BYTES,
|
||||||
memcpy(dest, src, destStride);
|
src += _colorSize * DataBlock::COLOR_BYTES) {
|
||||||
|
memcpy(dest, src, unextendedSize * DataBlock::COLOR_BYTES);
|
||||||
}
|
}
|
||||||
return unextended;
|
return unextended;
|
||||||
}
|
}
|
||||||
|
@ -1702,134 +1700,170 @@ public:
|
||||||
|
|
||||||
HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
|
HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
|
||||||
|
|
||||||
void init(HeightfieldBuffer* buffer) { _buffer = buffer; }
|
void init(HeightfieldBuffer* buffer);
|
||||||
|
|
||||||
virtual int visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
virtual bool postVisit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
const QVector<Box>& _intersections;
|
const QVector<Box>& _intersections;
|
||||||
HeightfieldBuffer* _buffer;
|
HeightfieldBuffer* _buffer;
|
||||||
|
|
||||||
|
int _heightDepth;
|
||||||
|
int _colorDepth;
|
||||||
|
int _materialDepth;
|
||||||
};
|
};
|
||||||
|
|
||||||
HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
|
HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
|
||||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
|
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
|
||||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod),
|
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
|
||||||
|
AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod),
|
||||||
_intersections(intersections) {
|
_intersections(intersections) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) {
|
||||||
|
_buffer = buffer;
|
||||||
|
_heightDepth = -1;
|
||||||
|
_colorDepth = -1;
|
||||||
|
_materialDepth = -1;
|
||||||
|
}
|
||||||
|
|
||||||
int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
||||||
Box bounds = info.getBounds();
|
if (!info.getBounds().intersects(_buffer->getHeightBounds())) {
|
||||||
const Box& heightBounds = _buffer->getHeightBounds();
|
|
||||||
if (!bounds.intersects(heightBounds)) {
|
|
||||||
return STOP_RECURSION;
|
return STOP_RECURSION;
|
||||||
}
|
}
|
||||||
if (!info.isLeaf && info.size > _buffer->getScale()) {
|
if (!info.isLeaf) {
|
||||||
return DEFAULT_ORDER;
|
return DEFAULT_ORDER;
|
||||||
}
|
}
|
||||||
|
postVisit(info);
|
||||||
|
return STOP_RECURSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) {
|
||||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||||
if (!height) {
|
if (height || _heightDepth != -1) {
|
||||||
return STOP_RECURSION;
|
if (_depth < _heightDepth) {
|
||||||
|
height.reset();
|
||||||
|
}
|
||||||
|
_heightDepth = _depth;
|
||||||
}
|
}
|
||||||
|
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
|
if (color || _colorDepth != -1) {
|
||||||
|
if (_depth < _colorDepth) {
|
||||||
|
color.reset();
|
||||||
|
}
|
||||||
|
_colorDepth = _depth;
|
||||||
|
}
|
||||||
|
HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
||||||
|
if (material || _materialDepth != -1) {
|
||||||
|
if (_depth < _materialDepth) {
|
||||||
|
material.reset();
|
||||||
|
}
|
||||||
|
_materialDepth = _depth;
|
||||||
|
}
|
||||||
|
if (!(height || color || material)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
Box bounds = info.getBounds();
|
||||||
foreach (const Box& intersection, _intersections) {
|
foreach (const Box& intersection, _intersections) {
|
||||||
Box overlap = intersection.getIntersection(bounds);
|
Box overlap = intersection.getIntersection(bounds);
|
||||||
if (overlap.isEmpty()) {
|
if (overlap.isEmpty()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
float heightIncrement = _buffer->getHeightIncrement();
|
if (height) {
|
||||||
int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement;
|
float heightIncrement = _buffer->getHeightIncrement();
|
||||||
int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement;
|
const Box& heightBounds = _buffer->getHeightBounds();
|
||||||
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement);
|
int destX = (overlap.minimum.x - heightBounds.minimum.x) / heightIncrement;
|
||||||
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement);
|
int destY = (overlap.minimum.z - heightBounds.minimum.z) / heightIncrement;
|
||||||
int heightSize = _buffer->getHeightSize();
|
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / heightIncrement);
|
||||||
char* dest = _buffer->getHeight().data() + destY * heightSize + destX;
|
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / heightIncrement);
|
||||||
|
int heightSize = _buffer->getHeightSize();
|
||||||
const QByteArray& srcHeight = height->getContents();
|
char* dest = _buffer->getHeight().data() + destY * heightSize + destX;
|
||||||
int srcSize = glm::sqrt(float(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;
|
const QByteArray& srcHeight = height->getContents();
|
||||||
for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) {
|
int srcSize = glm::sqrt((float)srcHeight.size());
|
||||||
memcpy(dest, src, destWidth);
|
float srcIncrement = info.size / srcSize;
|
||||||
}
|
|
||||||
} else {
|
if (info.size == _buffer->getScale() && srcSize == (heightSize - HeightfieldBuffer::HEIGHT_EXTENSION)) {
|
||||||
// more difficult: different resolutions
|
// easy case: same resolution
|
||||||
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
||||||
float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
||||||
float srcAdvance = heightIncrement / srcIncrement;
|
|
||||||
int shift = 0;
|
const char* src = srcHeight.constData() + srcY * srcSize + srcX;
|
||||||
float size = _buffer->getScale();
|
for (int y = 0; y < destHeight; y++, src += srcSize, dest += heightSize) {
|
||||||
while (size < info.size) {
|
memcpy(dest, src, destWidth);
|
||||||
shift++;
|
}
|
||||||
size *= 2.0f;
|
} else {
|
||||||
}
|
// more difficult: different resolutions
|
||||||
int subtract = (_buffer->getTranslation().y - info.minimum.y) * EIGHT_BIT_MAXIMUM / _buffer->getScale();
|
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
||||||
for (int y = 0; y < destHeight; y++, dest += heightSize, srcY += srcAdvance) {
|
float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
||||||
const uchar* src = (const uchar*)srcHeight.constData() + (int)srcY * srcSize;
|
float srcAdvance = heightIncrement / srcIncrement;
|
||||||
float lineSrcX = srcX;
|
int shift = 0;
|
||||||
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
|
float size = _buffer->getScale();
|
||||||
*lineDest = qMin(qMax(0, (src[(int)lineSrcX] << shift) - subtract), EIGHT_BIT_MAXIMUM);
|
while (size < info.size) {
|
||||||
|
shift++;
|
||||||
|
size *= 2.0f;
|
||||||
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (color) {
|
||||||
int colorSize = _buffer->getColorSize();
|
const Box& colorBounds = _buffer->getColorBounds();
|
||||||
if (colorSize == 0) {
|
overlap = colorBounds.getIntersection(overlap);
|
||||||
continue;
|
float colorIncrement = _buffer->getColorIncrement();
|
||||||
}
|
int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement;
|
||||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement;
|
||||||
if (!color) {
|
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement);
|
||||||
continue;
|
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement);
|
||||||
}
|
int colorSize = _buffer->getColorSize();
|
||||||
const Box& colorBounds = _buffer->getColorBounds();
|
char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES;
|
||||||
overlap = colorBounds.getIntersection(overlap);
|
int destStride = colorSize * DataBlock::COLOR_BYTES;
|
||||||
float colorIncrement = _buffer->getColorIncrement();
|
int destBytes = destWidth * DataBlock::COLOR_BYTES;
|
||||||
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) * DataBlock::COLOR_BYTES;
|
|
||||||
int destStride = colorSize * DataBlock::COLOR_BYTES;
|
|
||||||
int destBytes = destWidth * DataBlock::COLOR_BYTES;
|
|
||||||
|
|
||||||
const QByteArray& srcColor = color->getContents();
|
|
||||||
srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES));
|
|
||||||
int srcStride = srcSize * DataBlock::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) * DataBlock::COLOR_BYTES;
|
const QByteArray& srcColor = color->getContents();
|
||||||
for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {
|
int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES));
|
||||||
memcpy(dest, src, destBytes);
|
int srcStride = srcSize * DataBlock::COLOR_BYTES;
|
||||||
}
|
float srcIncrement = info.size / srcSize;
|
||||||
} else {
|
|
||||||
// more difficult: different resolutions
|
if (srcIncrement == colorIncrement) {
|
||||||
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
// easy case: same resolution
|
||||||
float srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
||||||
float srcAdvance = colorIncrement / srcIncrement;
|
int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
||||||
for (int y = 0; y < destHeight; y++, dest += destStride, srcY += srcAdvance) {
|
|
||||||
const char* src = srcColor.constData() + (int)srcY * srcStride;
|
const char* src = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::COLOR_BYTES;
|
||||||
float lineSrcX = srcX;
|
for (int y = 0; y < destHeight; y++, src += srcStride, dest += destStride) {
|
||||||
for (char* lineDest = dest, *end = dest + destBytes; lineDest != end; lineDest += DataBlock::COLOR_BYTES,
|
memcpy(dest, src, destBytes);
|
||||||
lineSrcX += srcAdvance) {
|
}
|
||||||
const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES;
|
} else {
|
||||||
lineDest[0] = lineSrc[0];
|
// more difficult: different resolutions
|
||||||
lineDest[1] = lineSrc[1];
|
float srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
||||||
lineDest[2] = lineSrc[2];
|
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 += DataBlock::COLOR_BYTES,
|
||||||
|
lineSrcX += srcAdvance) {
|
||||||
|
const char* lineSrc = src + (int)lineSrcX * DataBlock::COLOR_BYTES;
|
||||||
|
lineDest[0] = lineSrc[0];
|
||||||
|
lineDest[1] = lineSrc[1];
|
||||||
|
lineDest[2] = lineSrc[2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (material) {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return STOP_RECURSION;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
class HeightfieldRegionVisitor : public MetavoxelVisitor {
|
class HeightfieldRegionVisitor : public MetavoxelVisitor {
|
||||||
|
@ -1841,11 +1875,27 @@ public:
|
||||||
HeightfieldRegionVisitor(const MetavoxelLOD& lod);
|
HeightfieldRegionVisitor(const MetavoxelLOD& lod);
|
||||||
|
|
||||||
virtual int visit(MetavoxelInfo& info);
|
virtual int visit(MetavoxelInfo& info);
|
||||||
|
virtual bool postVisit(MetavoxelInfo& info);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void addRegion(const Box& unextended, const Box& extended);
|
void addRegion(const Box& unextended, const Box& extended);
|
||||||
|
|
||||||
|
int _heightSize;
|
||||||
|
int _heightDepth;
|
||||||
|
|
||||||
|
int _inheritedColorSize;
|
||||||
|
int _inheritedColorDepth;
|
||||||
|
|
||||||
|
int _containedColorSize;
|
||||||
|
int _containedColorDepth;
|
||||||
|
|
||||||
|
int _inheritedMaterialSize;
|
||||||
|
int _inheritedMaterialDepth;
|
||||||
|
|
||||||
|
int _containedMaterialSize;
|
||||||
|
int _containedMaterialDepth;
|
||||||
|
|
||||||
QVector<Box> _intersections;
|
QVector<Box> _intersections;
|
||||||
HeightfieldFetchVisitor _fetchVisitor;
|
HeightfieldFetchVisitor _fetchVisitor;
|
||||||
};
|
};
|
||||||
|
@ -1857,52 +1907,92 @@ HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
|
||||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
|
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
|
||||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
|
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
|
||||||
regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)),
|
regionBounds(glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX), glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX)),
|
||||||
|
_heightDepth(-1),
|
||||||
|
_inheritedColorDepth(-1),
|
||||||
|
_containedColorDepth(-1),
|
||||||
|
_inheritedMaterialDepth(-1),
|
||||||
|
_containedMaterialDepth(-1),
|
||||||
_fetchVisitor(lod, _intersections) {
|
_fetchVisitor(lod, _intersections) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int signedLeftShift(int value, int shift) {
|
||||||
|
return (shift > 0) ? value << shift : value >> (-shift);
|
||||||
|
}
|
||||||
|
|
||||||
int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
||||||
if (!info.isLeaf) {
|
|
||||||
return DEFAULT_ORDER;
|
|
||||||
}
|
|
||||||
HeightfieldBuffer* buffer = NULL;
|
|
||||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||||
|
int order = DEFAULT_ORDER;
|
||||||
if (height) {
|
if (height) {
|
||||||
const QByteArray& heightContents = height->getContents();
|
_heightSize = glm::sqrt((float)height->getContents().size());
|
||||||
int size = glm::sqrt(float(heightContents.size()));
|
_heightDepth = _depth;
|
||||||
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
|
order |= ALL_NODES_REST;
|
||||||
int heightContentsSize = extendedSize * extendedSize;
|
}
|
||||||
|
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
if (color) {
|
||||||
int colorContentsSize = 0;
|
int colorSize = glm::sqrt((float)(color->getContents().size() / DataBlock::COLOR_BYTES));
|
||||||
if (color) {
|
if (_heightDepth == -1) {
|
||||||
const QByteArray& colorContents = color->getContents();
|
_inheritedColorSize = colorSize;
|
||||||
int colorSize = glm::sqrt(float(colorContents.size() / DataBlock::COLOR_BYTES));
|
_inheritedColorDepth = _depth;
|
||||||
int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE;
|
|
||||||
colorContentsSize = extendedColorSize * extendedColorSize * DataBlock::COLOR_BYTES;
|
} else if (_containedColorDepth == -1 ||
|
||||||
|
colorSize > signedLeftShift(_containedColorSize, _containedColorDepth - _depth)) {
|
||||||
|
_containedColorSize = colorSize;
|
||||||
|
_containedColorDepth = _depth;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
||||||
|
if (material) {
|
||||||
|
int materialSize = glm::sqrt((float)material->getContents().size());
|
||||||
|
if (_heightDepth == -1) {
|
||||||
|
_inheritedMaterialSize = materialSize;
|
||||||
|
_inheritedMaterialDepth = _depth;
|
||||||
|
|
||||||
HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
} else if (_containedMaterialDepth == -1 ||
|
||||||
QByteArray materialContents;
|
materialSize > signedLeftShift(_containedMaterialSize, _containedMaterialDepth - _depth)) {
|
||||||
QVector<SharedObjectPointer> materials;
|
_containedMaterialSize = materialSize;
|
||||||
if (material) {
|
_containedMaterialDepth = _depth;
|
||||||
materialContents = material->getContents();
|
|
||||||
materials = material->getMaterials();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
if (!info.isLeaf) {
|
||||||
|
return order;
|
||||||
|
}
|
||||||
|
postVisit(info);
|
||||||
|
return STOP_RECURSION;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) {
|
||||||
|
HeightfieldBuffer* buffer = NULL;
|
||||||
|
if (_depth == _heightDepth) {
|
||||||
|
int extendedHeightSize = _heightSize + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||||
|
int heightContentsSize = extendedHeightSize * extendedHeightSize;
|
||||||
|
|
||||||
|
int extendedColorSize = qMax(_inheritedColorDepth == -1 ? 0 :
|
||||||
|
signedLeftShift(_inheritedColorSize, _inheritedColorDepth - _depth) + HeightfieldBuffer::SHARED_EDGE,
|
||||||
|
_containedColorDepth == -1 ? 0 :
|
||||||
|
signedLeftShift(_containedColorSize, _containedColorDepth - _depth) + HeightfieldBuffer::SHARED_EDGE);
|
||||||
|
int colorContentsSize = extendedColorSize * extendedColorSize;
|
||||||
|
|
||||||
|
int extendedMaterialSize = qMax(_inheritedMaterialDepth == -1 ? 0 :
|
||||||
|
signedLeftShift(_inheritedMaterialSize, _inheritedMaterialDepth - _depth) + HeightfieldBuffer::SHARED_EDGE,
|
||||||
|
_containedMaterialDepth == -1 ? 0 :
|
||||||
|
signedLeftShift(_containedMaterialSize, _containedMaterialDepth - _depth) + HeightfieldBuffer::SHARED_EDGE);
|
||||||
|
int materialContentsSize = extendedMaterialSize * extendedMaterialSize;
|
||||||
|
|
||||||
const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(
|
const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(
|
||||||
info.inputValues.at(3).getInlineValue<BufferDataPointer>().data());
|
info.inputValues.at(3).getInlineValue<BufferDataPointer>().data());
|
||||||
Box bounds = info.getBounds();
|
Box bounds = info.getBounds();
|
||||||
if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&
|
if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&
|
||||||
existingBuffer->getColor().size() == colorContentsSize) {
|
existingBuffer->getColor().size() == colorContentsSize &&
|
||||||
// we already have a buffer of the correct resolution
|
existingBuffer->getMaterial().size() == materialContentsSize) {
|
||||||
|
// we already have a buffer of the correct resolution
|
||||||
addRegion(bounds, existingBuffer->getHeightBounds());
|
addRegion(bounds, existingBuffer->getHeightBounds());
|
||||||
buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(),
|
buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(),
|
||||||
existingBuffer->getColor(), materialContents, materials);
|
existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials());
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// we must create a new buffer and update its borders
|
// we must create a new buffer and update its borders
|
||||||
buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0),
|
buffer = new HeightfieldBuffer(info.minimum, info.size, QByteArray(heightContentsSize, 0),
|
||||||
QByteArray(colorContentsSize, 0), materialContents, materials);
|
QByteArray(colorContentsSize, 0), QByteArray(materialContentsSize, 0));
|
||||||
const Box& heightBounds = buffer->getHeightBounds();
|
const Box& heightBounds = buffer->getHeightBounds();
|
||||||
addRegion(bounds, heightBounds);
|
addRegion(bounds, heightBounds);
|
||||||
|
|
||||||
|
@ -1919,10 +2009,17 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
||||||
_fetchVisitor.init(buffer);
|
_fetchVisitor.init(buffer);
|
||||||
_data->guide(_fetchVisitor);
|
_data->guide(_fetchVisitor);
|
||||||
}
|
}
|
||||||
|
_heightDepth = _containedColorDepth = _containedMaterialDepth = -1;
|
||||||
|
}
|
||||||
|
if (_depth == _inheritedColorDepth) {
|
||||||
|
_inheritedColorDepth = -1;
|
||||||
|
}
|
||||||
|
if (_depth == _inheritedMaterialDepth) {
|
||||||
|
_inheritedMaterialDepth = -1;
|
||||||
}
|
}
|
||||||
BufferDataPointer pointer(buffer);
|
BufferDataPointer pointer(buffer);
|
||||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||||
return STOP_RECURSION;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
|
void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
|
||||||
|
|
|
@ -249,7 +249,7 @@ public:
|
||||||
const QVector<SharedObjectPointer>& getMaterials() const { return _materials; }
|
const QVector<SharedObjectPointer>& getMaterials() const { return _materials; }
|
||||||
|
|
||||||
QByteArray getUnextendedHeight() const;
|
QByteArray getUnextendedHeight() const;
|
||||||
QByteArray getUnextendedColor() const;
|
QByteArray getUnextendedColor(int x = 0, int y = 0) const;
|
||||||
|
|
||||||
int getHeightSize() const { return _heightSize; }
|
int getHeightSize() const { return _heightSize; }
|
||||||
float getHeightIncrement() const { return _heightIncrement; }
|
float getHeightIncrement() const { return _heightIncrement; }
|
||||||
|
|
|
@ -1038,26 +1038,42 @@ void ImportHeightfieldTool::apply() {
|
||||||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
|
||||||
AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer))));
|
AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer))));
|
||||||
|
|
||||||
QByteArray color;
|
|
||||||
if (buffer->getColor().isEmpty()) {
|
|
||||||
const unsigned char WHITE_VALUE = 0xFF;
|
|
||||||
color = QByteArray(height.size() * DataBlock::COLOR_BYTES, WHITE_VALUE);
|
|
||||||
} else {
|
|
||||||
color = buffer->getUnextendedColor();
|
|
||||||
}
|
|
||||||
HeightfieldColorDataPointer colorPointer(new HeightfieldColorData(color));
|
|
||||||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(AttributeValue(
|
|
||||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), encodeInline(colorPointer))));
|
|
||||||
|
|
||||||
int size = glm::sqrt(float(height.size()));
|
|
||||||
QByteArray material(size * size, 0);
|
|
||||||
HeightfieldMaterialDataPointer materialPointer(new HeightfieldMaterialData(material));
|
|
||||||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), new MetavoxelNode(AttributeValue(
|
|
||||||
AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), encodeInline(materialPointer))));
|
|
||||||
|
|
||||||
MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit(
|
MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit(
|
||||||
_translation->getValue() + buffer->getTranslation() * scale, data)) };
|
_translation->getValue() + buffer->getTranslation() * scale, data)) };
|
||||||
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
|
|
||||||
|
int colorUnits = buffer->getColor().isEmpty() ? 1 : (buffer->getColorSize() - HeightfieldBuffer::SHARED_EDGE) /
|
||||||
|
(buffer->getHeightSize() - HeightfieldBuffer::HEIGHT_EXTENSION);
|
||||||
|
float colorScale = scale / colorUnits;
|
||||||
|
|
||||||
|
for (int y = 0; y < colorUnits; y++) {
|
||||||
|
for (int x = 0; x < colorUnits; x++) {
|
||||||
|
MetavoxelData data;
|
||||||
|
data.setSize(colorScale);
|
||||||
|
|
||||||
|
QByteArray color;
|
||||||
|
if (buffer->getColor().isEmpty()) {
|
||||||
|
const unsigned char WHITE_VALUE = 0xFF;
|
||||||
|
color = QByteArray(height.size() * DataBlock::COLOR_BYTES, WHITE_VALUE);
|
||||||
|
} else {
|
||||||
|
color = buffer->getUnextendedColor(x, y);
|
||||||
|
}
|
||||||
|
HeightfieldColorDataPointer colorPointer(new HeightfieldColorData(color));
|
||||||
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(
|
||||||
|
AttributeValue(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(),
|
||||||
|
encodeInline(colorPointer))));
|
||||||
|
|
||||||
|
QByteArray material(height.size(), 0);
|
||||||
|
HeightfieldMaterialDataPointer materialPointer(new HeightfieldMaterialData(material));
|
||||||
|
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), new MetavoxelNode(
|
||||||
|
AttributeValue(AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(),
|
||||||
|
encodeInline(materialPointer))));
|
||||||
|
|
||||||
|
MetavoxelEditMessage message = { QVariant::fromValue(SetDataEdit(
|
||||||
|
_translation->getValue() + buffer->getTranslation() * scale + glm::vec3(x, 0.0f, y) * colorScale, data)) };
|
||||||
|
Application::getInstance()->getMetavoxels()->applyEdit(message, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1143,8 +1159,8 @@ void ImportHeightfieldTool::updatePreview() {
|
||||||
float z = 0.0f;
|
float z = 0.0f;
|
||||||
int blockSize = pow(2.0, _blockSize->value());
|
int blockSize = pow(2.0, _blockSize->value());
|
||||||
int heightSize = blockSize + HeightfieldBuffer::HEIGHT_EXTENSION;
|
int heightSize = blockSize + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||||
int colorScale = glm::round(glm::log(_colorImage.height() / _heightImage.height()) / glm::log(2.0f));
|
int colorScale = glm::round(glm::log(_colorImage.height() / (float)_heightImage.height()) / glm::log(2.0f));
|
||||||
int colorBlockSize = blockSize * pow(2.0, colorScale);
|
int colorBlockSize = blockSize * pow(2.0, qMax(colorScale, 0));
|
||||||
int colorSize = colorBlockSize + HeightfieldBuffer::SHARED_EDGE;
|
int colorSize = colorBlockSize + HeightfieldBuffer::SHARED_EDGE;
|
||||||
for (int i = 0; i < _heightImage.height(); i += blockSize, z++) {
|
for (int i = 0; i < _heightImage.height(); i += blockSize, z++) {
|
||||||
float x = 0.0f;
|
float x = 0.0f;
|
||||||
|
|
|
@ -1198,6 +1198,10 @@ bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttributeValue HeightfieldAttribute::inherit(const AttributeValue& parentValue) const {
|
||||||
|
return AttributeValue(parentValue.getAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) :
|
HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) :
|
||||||
InlineAttribute<HeightfieldColorDataPointer>(name) {
|
InlineAttribute<HeightfieldColorDataPointer>(name) {
|
||||||
}
|
}
|
||||||
|
@ -1337,6 +1341,10 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttributeValue HeightfieldColorAttribute::inherit(const AttributeValue& parentValue) const {
|
||||||
|
return AttributeValue(parentValue.getAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
HeightfieldMaterialAttribute::HeightfieldMaterialAttribute(const QString& name) :
|
HeightfieldMaterialAttribute::HeightfieldMaterialAttribute(const QString& name) :
|
||||||
InlineAttribute<HeightfieldMaterialDataPointer>(name) {
|
InlineAttribute<HeightfieldMaterialDataPointer>(name) {
|
||||||
}
|
}
|
||||||
|
@ -1404,6 +1412,10 @@ bool HeightfieldMaterialAttribute::merge(void*& parent, void* children[], bool p
|
||||||
return maxSize == 0;
|
return maxSize == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AttributeValue HeightfieldMaterialAttribute::inherit(const AttributeValue& parentValue) const {
|
||||||
|
return AttributeValue(parentValue.getAttribute());
|
||||||
|
}
|
||||||
|
|
||||||
const int VOXEL_COLOR_HEADER_SIZE = sizeof(qint32) * 6;
|
const int VOXEL_COLOR_HEADER_SIZE = sizeof(qint32) * 6;
|
||||||
|
|
||||||
static QByteArray encodeVoxelColor(int offsetX, int offsetY, int offsetZ,
|
static QByteArray encodeVoxelColor(int offsetX, int offsetY, int offsetZ,
|
||||||
|
|
|
@ -536,6 +536,8 @@ public:
|
||||||
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
||||||
|
|
||||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||||
|
|
||||||
|
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QExplicitlySharedDataPointer<HeightfieldColorData> HeightfieldColorDataPointer;
|
typedef QExplicitlySharedDataPointer<HeightfieldColorData> HeightfieldColorDataPointer;
|
||||||
|
@ -580,6 +582,8 @@ public:
|
||||||
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
||||||
|
|
||||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||||
|
|
||||||
|
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QExplicitlySharedDataPointer<HeightfieldMaterialData> HeightfieldMaterialDataPointer;
|
typedef QExplicitlySharedDataPointer<HeightfieldMaterialData> HeightfieldMaterialDataPointer;
|
||||||
|
@ -646,6 +650,8 @@ public:
|
||||||
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
||||||
|
|
||||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||||
|
|
||||||
|
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QExplicitlySharedDataPointer<VoxelColorData> VoxelColorDataPointer;
|
typedef QExplicitlySharedDataPointer<VoxelColorData> VoxelColorDataPointer;
|
||||||
|
|
Loading…
Reference in a new issue