mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 17:55:36 +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;
|
||||
}
|
||||
|
||||
QByteArray HeightfieldBuffer::getUnextendedColor() const {
|
||||
int srcSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES));
|
||||
int destSize = srcSize - 1;
|
||||
QByteArray unextended(destSize * destSize * DataBlock::COLOR_BYTES, 0);
|
||||
const char* src = _color.constData();
|
||||
int srcStride = srcSize * DataBlock::COLOR_BYTES;
|
||||
QByteArray HeightfieldBuffer::getUnextendedColor(int x, int y) const {
|
||||
int unextendedSize = _heightSize - HEIGHT_EXTENSION;
|
||||
QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0);
|
||||
char* dest = unextended.data();
|
||||
int destStride = destSize * DataBlock::COLOR_BYTES;
|
||||
for (int z = 0; z < destSize; z++, src += srcStride, dest += destStride) {
|
||||
memcpy(dest, src, destStride);
|
||||
const char* src = _color.constData() + (y * _colorSize + x) * unextendedSize * DataBlock::COLOR_BYTES;
|
||||
for (int z = 0; z < unextendedSize; z++, dest += unextendedSize * DataBlock::COLOR_BYTES,
|
||||
src += _colorSize * DataBlock::COLOR_BYTES) {
|
||||
memcpy(dest, src, unextendedSize * DataBlock::COLOR_BYTES);
|
||||
}
|
||||
return unextended;
|
||||
}
|
||||
|
@ -1702,134 +1700,170 @@ public:
|
|||
|
||||
HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
|
||||
|
||||
void init(HeightfieldBuffer* buffer) { _buffer = buffer; }
|
||||
void init(HeightfieldBuffer* buffer);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
const QVector<Box>& _intersections;
|
||||
HeightfieldBuffer* _buffer;
|
||||
|
||||
int _heightDepth;
|
||||
int _colorDepth;
|
||||
int _materialDepth;
|
||||
};
|
||||
|
||||
HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), QVector<AttributePointer>(), lod),
|
||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod),
|
||||
_intersections(intersections) {
|
||||
}
|
||||
|
||||
void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) {
|
||||
_buffer = buffer;
|
||||
_heightDepth = -1;
|
||||
_colorDepth = -1;
|
||||
_materialDepth = -1;
|
||||
}
|
||||
|
||||
int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
||||
Box bounds = info.getBounds();
|
||||
const Box& heightBounds = _buffer->getHeightBounds();
|
||||
if (!bounds.intersects(heightBounds)) {
|
||||
if (!info.getBounds().intersects(_buffer->getHeightBounds())) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (!info.isLeaf && info.size > _buffer->getScale()) {
|
||||
if (!info.isLeaf) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
postVisit(info);
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) {
|
||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||
if (!height) {
|
||||
return STOP_RECURSION;
|
||||
if (height || _heightDepth != -1) {
|
||||
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) {
|
||||
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 QByteArray& srcHeight = height->getContents();
|
||||
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;
|
||||
if (height) {
|
||||
float heightIncrement = _buffer->getHeightIncrement();
|
||||
const Box& heightBounds = _buffer->getHeightBounds();
|
||||
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);
|
||||
}
|
||||
} 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;
|
||||
}
|
||||
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);
|
||||
const QByteArray& srcHeight = height->getContents();
|
||||
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;
|
||||
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;
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int colorSize = _buffer->getColorSize();
|
||||
if (colorSize == 0) {
|
||||
continue;
|
||||
}
|
||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
if (!color) {
|
||||
continue;
|
||||
}
|
||||
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) * 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;
|
||||
if (color) {
|
||||
const Box& colorBounds = _buffer->getColorBounds();
|
||||
overlap = colorBounds.getIntersection(overlap);
|
||||
float colorIncrement = _buffer->getColorIncrement();
|
||||
int destX = (overlap.minimum.x - colorBounds.minimum.x) / colorIncrement;
|
||||
int destY = (overlap.minimum.z - colorBounds.minimum.z) / colorIncrement;
|
||||
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / colorIncrement);
|
||||
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / colorIncrement);
|
||||
int colorSize = _buffer->getColorSize();
|
||||
char* dest = _buffer->getColor().data() + (destY * colorSize + destX) * DataBlock::COLOR_BYTES;
|
||||
int destStride = colorSize * DataBlock::COLOR_BYTES;
|
||||
int destBytes = destWidth * DataBlock::COLOR_BYTES;
|
||||
|
||||
const char* src = srcColor.constData() + (srcY * srcSize + srcX) * DataBlock::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 += 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];
|
||||
const QByteArray& srcColor = color->getContents();
|
||||
int srcSize = glm::sqrt(float(srcColor.size() / DataBlock::COLOR_BYTES));
|
||||
int srcStride = srcSize * DataBlock::COLOR_BYTES;
|
||||
float 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;
|
||||
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 += 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 {
|
||||
|
@ -1841,11 +1875,27 @@ public:
|
|||
HeightfieldRegionVisitor(const MetavoxelLOD& lod);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
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;
|
||||
HeightfieldFetchVisitor _fetchVisitor;
|
||||
};
|
||||
|
@ -1857,52 +1907,92 @@ HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
|
|||
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)),
|
||||
_heightDepth(-1),
|
||||
_inheritedColorDepth(-1),
|
||||
_containedColorDepth(-1),
|
||||
_inheritedMaterialDepth(-1),
|
||||
_containedMaterialDepth(-1),
|
||||
_fetchVisitor(lod, _intersections) {
|
||||
}
|
||||
|
||||
static int signedLeftShift(int value, int shift) {
|
||||
return (shift > 0) ? value << shift : value >> (-shift);
|
||||
}
|
||||
|
||||
int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.isLeaf) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
HeightfieldBuffer* buffer = NULL;
|
||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||
int order = DEFAULT_ORDER;
|
||||
if (height) {
|
||||
const QByteArray& heightContents = height->getContents();
|
||||
int size = glm::sqrt(float(heightContents.size()));
|
||||
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||
int heightContentsSize = extendedSize * extendedSize;
|
||||
|
||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
int colorContentsSize = 0;
|
||||
if (color) {
|
||||
const QByteArray& colorContents = color->getContents();
|
||||
int colorSize = glm::sqrt(float(colorContents.size() / DataBlock::COLOR_BYTES));
|
||||
int extendedColorSize = colorSize + HeightfieldBuffer::SHARED_EDGE;
|
||||
colorContentsSize = extendedColorSize * extendedColorSize * DataBlock::COLOR_BYTES;
|
||||
_heightSize = glm::sqrt((float)height->getContents().size());
|
||||
_heightDepth = _depth;
|
||||
order |= ALL_NODES_REST;
|
||||
}
|
||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
if (color) {
|
||||
int colorSize = glm::sqrt((float)(color->getContents().size() / DataBlock::COLOR_BYTES));
|
||||
if (_heightDepth == -1) {
|
||||
_inheritedColorSize = colorSize;
|
||||
_inheritedColorDepth = _depth;
|
||||
|
||||
} 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>();
|
||||
QByteArray materialContents;
|
||||
QVector<SharedObjectPointer> materials;
|
||||
if (material) {
|
||||
materialContents = material->getContents();
|
||||
materials = material->getMaterials();
|
||||
} else if (_containedMaterialDepth == -1 ||
|
||||
materialSize > signedLeftShift(_containedMaterialSize, _containedMaterialDepth - _depth)) {
|
||||
_containedMaterialSize = materialSize;
|
||||
_containedMaterialDepth = _depth;
|
||||
}
|
||||
}
|
||||
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*>(
|
||||
info.inputValues.at(3).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
|
||||
existingBuffer->getColor().size() == colorContentsSize &&
|
||||
existingBuffer->getMaterial().size() == materialContentsSize) {
|
||||
// we already have a buffer of the correct resolution
|
||||
addRegion(bounds, existingBuffer->getHeightBounds());
|
||||
buffer = new HeightfieldBuffer(info.minimum, info.size, existingBuffer->getHeight(),
|
||||
existingBuffer->getColor(), materialContents, materials);
|
||||
|
||||
existingBuffer->getColor(), existingBuffer->getMaterial(), existingBuffer->getMaterials());
|
||||
|
||||
} else {
|
||||
// we must create a new buffer and update its borders
|
||||
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();
|
||||
addRegion(bounds, heightBounds);
|
||||
|
||||
|
@ -1919,10 +2009,17 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
|||
_fetchVisitor.init(buffer);
|
||||
_data->guide(_fetchVisitor);
|
||||
}
|
||||
_heightDepth = _containedColorDepth = _containedMaterialDepth = -1;
|
||||
}
|
||||
if (_depth == _inheritedColorDepth) {
|
||||
_inheritedColorDepth = -1;
|
||||
}
|
||||
if (_depth == _inheritedMaterialDepth) {
|
||||
_inheritedMaterialDepth = -1;
|
||||
}
|
||||
BufferDataPointer pointer(buffer);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||
return STOP_RECURSION;
|
||||
return true;
|
||||
}
|
||||
|
||||
void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
|
||||
|
|
|
@ -249,7 +249,7 @@ public:
|
|||
const QVector<SharedObjectPointer>& getMaterials() const { return _materials; }
|
||||
|
||||
QByteArray getUnextendedHeight() const;
|
||||
QByteArray getUnextendedColor() const;
|
||||
QByteArray getUnextendedColor(int x = 0, int y = 0) const;
|
||||
|
||||
int getHeightSize() const { return _heightSize; }
|
||||
float getHeightIncrement() const { return _heightIncrement; }
|
||||
|
|
|
@ -1038,26 +1038,42 @@ void ImportHeightfieldTool::apply() {
|
|||
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
|
||||
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(
|
||||
_translation->getValue() + buffer->getTranslation() * scale, data)) };
|
||||
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;
|
||||
int blockSize = pow(2.0, _blockSize->value());
|
||||
int heightSize = blockSize + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||
int colorScale = glm::round(glm::log(_colorImage.height() / _heightImage.height()) / glm::log(2.0f));
|
||||
int colorBlockSize = blockSize * pow(2.0, colorScale);
|
||||
int colorScale = glm::round(glm::log(_colorImage.height() / (float)_heightImage.height()) / glm::log(2.0f));
|
||||
int colorBlockSize = blockSize * pow(2.0, qMax(colorScale, 0));
|
||||
int colorSize = colorBlockSize + HeightfieldBuffer::SHARED_EDGE;
|
||||
for (int i = 0; i < _heightImage.height(); i += blockSize, z++) {
|
||||
float x = 0.0f;
|
||||
|
|
|
@ -1198,6 +1198,10 @@ bool HeightfieldAttribute::merge(void*& parent, void* children[], bool postRead)
|
|||
return false;
|
||||
}
|
||||
|
||||
AttributeValue HeightfieldAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
HeightfieldColorAttribute::HeightfieldColorAttribute(const QString& name) :
|
||||
InlineAttribute<HeightfieldColorDataPointer>(name) {
|
||||
}
|
||||
|
@ -1337,6 +1341,10 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
|
|||
return false;
|
||||
}
|
||||
|
||||
AttributeValue HeightfieldColorAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
HeightfieldMaterialAttribute::HeightfieldMaterialAttribute(const QString& name) :
|
||||
InlineAttribute<HeightfieldMaterialDataPointer>(name) {
|
||||
}
|
||||
|
@ -1404,6 +1412,10 @@ bool HeightfieldMaterialAttribute::merge(void*& parent, void* children[], bool p
|
|||
return maxSize == 0;
|
||||
}
|
||||
|
||||
AttributeValue HeightfieldMaterialAttribute::inherit(const AttributeValue& parentValue) const {
|
||||
return AttributeValue(parentValue.getAttribute());
|
||||
}
|
||||
|
||||
const int VOXEL_COLOR_HEADER_SIZE = sizeof(qint32) * 6;
|
||||
|
||||
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 bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<HeightfieldColorData> HeightfieldColorDataPointer;
|
||||
|
@ -580,6 +582,8 @@ public:
|
|||
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<HeightfieldMaterialData> HeightfieldMaterialDataPointer;
|
||||
|
@ -646,6 +650,8 @@ public:
|
|||
virtual void writeDelta(Bitstream& out, void* value, void* reference, bool isLeaf) const;
|
||||
|
||||
virtual bool merge(void*& parent, void* children[], bool postRead = false) const;
|
||||
|
||||
virtual AttributeValue inherit(const AttributeValue& parentValue) const;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<VoxelColorData> VoxelColorDataPointer;
|
||||
|
|
Loading…
Reference in a new issue