Attempting to remove some number magic.

This commit is contained in:
Andrzej Kapolka 2014-08-12 12:01:07 -07:00
parent 24cc90c1db
commit ee01d85b5e
5 changed files with 95 additions and 73 deletions

View file

@ -333,12 +333,11 @@ void PointBuffer::render(bool cursor) {
}
HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,
const QByteArray& height, const QByteArray& color, bool clearAfterLoading) :
const QByteArray& height, const QByteArray& color) :
_translation(translation),
_scale(scale),
_height(height),
_color(color),
_clearAfterLoading(clearAfterLoading),
_heightTextureID(0),
_colorTextureID(0),
_heightSize(glm::sqrt(height.size())) {
@ -355,6 +354,32 @@ HeightfieldBuffer::~HeightfieldBuffer() {
}
}
QByteArray HeightfieldBuffer::getUnextendedHeight() const {
int srcSize = glm::sqrt(_height.size());
int destSize = srcSize - 3;
QByteArray unextended(destSize * destSize, 0);
const char* src = _height.constData() + srcSize + 1;
char* dest = unextended.data();
for (int z = 0; z < destSize; z++, src += srcSize, dest += destSize) {
memcpy(dest, src, destSize);
}
return unextended;
}
QByteArray HeightfieldBuffer::getUnextendedColor() const {
int srcSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES);
int destSize = srcSize - 1;
QByteArray unextended(destSize * destSize * HeightfieldData::COLOR_BYTES, 0);
const char* src = _color.constData();
int srcStride = srcSize * HeightfieldData::COLOR_BYTES;
char* dest = unextended.data();
int destStride = destSize * HeightfieldData::COLOR_BYTES;
for (int z = 0; z < destSize; z++, src += srcStride, dest += destStride) {
memcpy(dest, src, destStride);
}
return unextended;
}
class HeightfieldPoint {
public:
glm::vec2 textureCoord;
@ -372,9 +397,6 @@ void HeightfieldBuffer::render(bool cursor) {
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, _heightSize, _heightSize, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, _height.constData());
if (_clearAfterLoading) {
_height.clear();
}
glGenTextures(1, &_colorTextureID);
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
@ -386,15 +408,12 @@ void HeightfieldBuffer::render(bool cursor) {
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR);
} else {
int colorSize = glm::sqrt(_color.size() / 3);
int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES);
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData());
if (_clearAfterLoading) {
_color.clear();
}
}
}
// create the buffer objects lazily
int innerSize = _heightSize - 2;
int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER;
int vertexCount = _heightSize * _heightSize;
int rows = _heightSize - 1;
int indexCount = rows * rows * 4;
@ -682,9 +701,9 @@ int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) {
if (height) {
const QByteArray& heightContents = height->getContents();
int size = glm::sqrt(heightContents.size());
int extendedSize = size + 3;
int extendedSize = size + HeightfieldBuffer::HEIGHT_EXTENSION;
QByteArray extendedHeightContents(extendedSize * extendedSize, 0);
char* dest = extendedHeightContents.data() + extendedSize + 1;
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);
@ -693,14 +712,13 @@ int HeightfieldAugmentVisitor::visit(MetavoxelInfo& info) {
HeightfieldDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldDataPointer>();
if (color) {
const QByteArray& colorContents = color->getContents();
const int BYTES_PER_PIXEL = 3;
int colorSize = glm::sqrt(colorContents.size() / BYTES_PER_PIXEL);
int extendedColorSize = colorSize + 1;
extendedColorContents = QByteArray(extendedColorSize * extendedColorSize * BYTES_PER_PIXEL, 0);
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 * BYTES_PER_PIXEL;
int destStride = extendedColorSize * BYTES_PER_PIXEL;
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);
}

View file

@ -131,10 +131,11 @@ private:
class HeightfieldBuffer : public BufferData {
public:
/// Creates a new heightfield buffer.
/// \param clearAfterLoading if true, clear the data arrays after we load them into textures in order to reclaim the space
HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color,
bool clearAfterLoading = true);
static const int HEIGHT_BORDER = 1;
static const int SHARED_EDGE = 1;
static const int HEIGHT_EXTENSION = 2 * HEIGHT_BORDER + SHARED_EDGE;
HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color);
~HeightfieldBuffer();
const glm::vec3& getTranslation() const { return _translation; }
@ -142,6 +143,9 @@ public:
const QByteArray& getHeight() const { return _height; }
const QByteArray& getColor() const { return _color; }
QByteArray getUnextendedHeight() const;
QByteArray getUnextendedColor() const;
virtual void render(bool cursor = false);
private:
@ -150,7 +154,6 @@ private:
float _scale;
QByteArray _height;
QByteArray _color;
bool _clearAfterLoading;
GLuint _heightTextureID;
GLuint _colorTextureID;
int _heightSize;

View file

@ -956,11 +956,11 @@ void ImportHeightfieldTool::apply() {
HeightfieldBuffer* buffer = static_cast<HeightfieldBuffer*>(bufferData.data());
MetavoxelData data;
data.setSize(scale);
HeightfieldDataPointer heightPointer(new HeightfieldData(buffer->getHeight()));
HeightfieldDataPointer heightPointer(new HeightfieldData(buffer->getUnextendedHeight()));
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldAttribute(), new MetavoxelNode(AttributeValue(
AttributeRegistry::getInstance()->getHeightfieldAttribute(), encodeInline(heightPointer))));
if (!buffer->getColor().isEmpty()) {
HeightfieldDataPointer colorPointer(new HeightfieldData(buffer->getColor()));
HeightfieldDataPointer colorPointer(new HeightfieldData(buffer->getUnextendedColor()));
data.setRoot(AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), new MetavoxelNode(AttributeValue(
AttributeRegistry::getInstance()->getHeightfieldColorAttribute(), encodeInline(colorPointer))));
}
@ -1003,38 +1003,38 @@ void ImportHeightfieldTool::updatePreview() {
if (_heightImage.width() > 0 && _heightImage.height() > 0) {
float z = 0.0f;
int blockSize = pow(2.0, _blockSize->value());
int heightSize = blockSize + 3;
int colorSize = blockSize + 1;
int heightSize = blockSize + HeightfieldBuffer::HEIGHT_EXTENSION;
int colorSize = blockSize + HeightfieldBuffer::SHARED_EDGE;
for (int i = 0; i < _heightImage.height(); i += blockSize, z++) {
float x = 0.0f;
for (int j = 0; j < _heightImage.width(); j += blockSize, x++) {
QByteArray height(heightSize * heightSize, 0);
int extendedI = qMax(i - 1, 0);
int extendedJ = qMax(j - 1, 0);
int offsetY = extendedI - i + 1;
int offsetX = extendedJ - j + 1;
int extendedI = qMax(i - HeightfieldBuffer::HEIGHT_BORDER, 0);
int extendedJ = qMax(j - HeightfieldBuffer::HEIGHT_BORDER, 0);
int offsetY = extendedI - i + HeightfieldBuffer::HEIGHT_BORDER;
int offsetX = extendedJ - j + HeightfieldBuffer::HEIGHT_BORDER;
int rows = qMin(heightSize - offsetY, _heightImage.height() - extendedI);
int columns = qMin(heightSize - offsetX, _heightImage.width() - extendedJ);
const int BYTES_PER_COLOR = 3;
for (int y = 0; y < rows; y++) {
uchar* src = _heightImage.scanLine(extendedI + y) + extendedJ * BYTES_PER_COLOR;
uchar* src = _heightImage.scanLine(extendedI + y) + extendedJ * HeightfieldData::COLOR_BYTES;
char* dest = height.data() + (y + offsetY) * heightSize + offsetX;
for (int x = 0; x < columns; x++) {
*dest++ = *src;
src += BYTES_PER_COLOR;
src += HeightfieldData::COLOR_BYTES;
}
}
QByteArray color;
if (!_colorImage.isNull()) {
color = QByteArray(colorSize * colorSize * BYTES_PER_COLOR, 0);
color = QByteArray(colorSize * colorSize * HeightfieldData::COLOR_BYTES, 0);
rows = qMax(0, qMin(colorSize, _colorImage.height() - i));
columns = qMax(0, qMin(colorSize, _colorImage.width() - j));
for (int y = 0; y < rows; y++) {
memcpy(color.data() + y * colorSize * BYTES_PER_COLOR,
_colorImage.scanLine(i + y) + j * BYTES_PER_COLOR, columns * BYTES_PER_COLOR);
memcpy(color.data() + y * colorSize * HeightfieldData::COLOR_BYTES,
_colorImage.scanLine(i + y) + j * HeightfieldData::COLOR_BYTES,
columns * HeightfieldData::COLOR_BYTES);
}
}
buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color, false)));
buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color)));
}
}
}

View file

@ -489,9 +489,6 @@ HeightfieldData::HeightfieldData(const QByteArray& contents) :
_contents(contents) {
}
const int BYTES_PER_PIXEL = 3;
const int ZERO_OFFSET = 128;
HeightfieldData::HeightfieldData(Bitstream& in, int bytes, bool color) {
read(in, bytes, color);
}
@ -515,10 +512,10 @@ HeightfieldData::HeightfieldData(Bitstream& in, int bytes, const HeightfieldData
int minX = offset.x() - 1;
int minY = offset.y() - 1;
if (color) {
int size = glm::sqrt(_contents.size() / (float)BYTES_PER_PIXEL);
char* dest = _contents.data() + (minY * size + minX) * BYTES_PER_PIXEL;
int destStride = size * BYTES_PER_PIXEL;
int srcStride = image.width() * BYTES_PER_PIXEL;
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
char* dest = _contents.data() + (minY * size + minX) * COLOR_BYTES;
int destStride = size * COLOR_BYTES;
int srcStride = image.width() * COLOR_BYTES;
for (int y = 0; y < image.height(); y++) {
memcpy(dest, image.constScanLine(y), srcStride);
dest += destStride;
@ -528,7 +525,7 @@ HeightfieldData::HeightfieldData(Bitstream& in, int bytes, const HeightfieldData
char* lineDest = _contents.data() + minY * size + minX;
for (int y = 0; y < image.height(); y++) {
const uchar* src = image.constScanLine(y);
for (char* dest = lineDest, *end = dest + image.width(); dest != end; dest++, src += BYTES_PER_PIXEL) {
for (char* dest = lineDest, *end = dest + image.width(); dest != end; dest++, src += COLOR_BYTES) {
*dest = *src;
}
lineDest += size;
@ -541,7 +538,7 @@ void HeightfieldData::write(Bitstream& out, bool color) {
if (_encoded.isEmpty()) {
QImage image;
if (color) {
int size = glm::sqrt(_contents.size() / (float)BYTES_PER_PIXEL);
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
image = QImage((uchar*)_contents.data(), size, size, QImage::Format_RGB888);
} else {
int size = glm::sqrt((float)_contents.size());
@ -571,7 +568,7 @@ void HeightfieldData::writeDelta(Bitstream& out, const HeightfieldDataPointer& r
QImage image;
int minX, minY;
if (color) {
int size = glm::sqrt(_contents.size() / (float)BYTES_PER_PIXEL);
int size = glm::sqrt(_contents.size() / (float)COLOR_BYTES);
minX = size;
minY = size;
int maxX = -1, maxY = -1;
@ -579,7 +576,7 @@ void HeightfieldData::writeDelta(Bitstream& out, const HeightfieldDataPointer& r
const char* ref = reference->_contents.constData();
for (int y = 0; y < size; y++) {
bool difference = false;
for (int x = 0; x < size; x++, src += BYTES_PER_PIXEL, ref += BYTES_PER_PIXEL) {
for (int x = 0; x < size; x++, src += COLOR_BYTES, ref += COLOR_BYTES) {
if (src[0] != ref[0] || src[1] != ref[1] || src[2] != ref[2]) {
minX = qMin(minX, x);
maxX = qMax(maxX, x);
@ -594,9 +591,9 @@ void HeightfieldData::writeDelta(Bitstream& out, const HeightfieldDataPointer& r
int width = qMax(maxX - minX + 1, 0);
int height = qMax(maxY - minY + 1, 0);
image = QImage(width, height, QImage::Format_RGB888);
src = _contents.constData() + (minY * size + minX) * BYTES_PER_PIXEL;
int srcStride = size * BYTES_PER_PIXEL;
int destStride = width * BYTES_PER_PIXEL;
src = _contents.constData() + (minY * size + minX) * COLOR_BYTES;
int srcStride = size * COLOR_BYTES;
int destStride = width * COLOR_BYTES;
for (int y = 0; y < height; y++) {
memcpy(image.scanLine(y), src, destStride);
src += srcStride;
@ -652,14 +649,14 @@ void HeightfieldData::read(Bitstream& in, int bytes, bool color) {
void HeightfieldData::set(const QImage& image, bool color) {
if (color) {
_contents.resize(image.width() * image.height() * BYTES_PER_PIXEL);
_contents.resize(image.width() * image.height() * COLOR_BYTES);
memcpy(_contents.data(), image.constBits(), _contents.size());
} else {
_contents.resize(image.width() * image.height());
char* dest = _contents.data();
for (const uchar* src = image.constBits(), *end = src + _contents.size() * BYTES_PER_PIXEL;
src != end; src += BYTES_PER_PIXEL) {
for (const uchar* src = image.constBits(), *end = src + _contents.size() * COLOR_BYTES;
src != end; src += COLOR_BYTES) {
*dest++ = *src;
}
}
@ -856,8 +853,8 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
*(HeightfieldDataPointer*)&parent = HeightfieldDataPointer();
return true;
}
int size = glm::sqrt(maxSize / (float)BYTES_PER_PIXEL);
QByteArray contents(size * size * BYTES_PER_PIXEL, 0);
int size = glm::sqrt(maxSize / (float)HeightfieldData::COLOR_BYTES);
QByteArray contents(size * size * HeightfieldData::COLOR_BYTES, 0);
int halfSize = size / 2;
for (int i = 0; i < MERGE_COUNT; i++) {
HeightfieldDataPointer child = decodeInline<HeightfieldDataPointer>(children[i]);
@ -865,7 +862,7 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
continue;
}
const QByteArray& childContents = child->getContents();
int childSize = glm::sqrt(childContents.size() / (float)BYTES_PER_PIXEL);
int childSize = glm::sqrt(childContents.size() / (float)HeightfieldData::COLOR_BYTES);
const int INDEX_MASK = 1;
int xIndex = i & INDEX_MASK;
const int Y_SHIFT = 1;
@ -875,24 +872,25 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
}
int Z_SHIFT = 2;
int zIndex = (i >> Z_SHIFT) & INDEX_MASK;
char* dest = contents.data() + ((zIndex * halfSize * size) + (xIndex * halfSize)) * BYTES_PER_PIXEL;
char* dest = contents.data() + ((zIndex * halfSize * size) + (xIndex * halfSize)) * HeightfieldData::COLOR_BYTES;
uchar* src = (uchar*)childContents.data();
int childStride = childSize * BYTES_PER_PIXEL;
int stride = size * BYTES_PER_PIXEL;
int childStride = childSize * HeightfieldData::COLOR_BYTES;
int stride = size * HeightfieldData::COLOR_BYTES;
int halfStride = stride / 2;
int childStep = 2 * BYTES_PER_PIXEL;
int redOffset3 = childStride + BYTES_PER_PIXEL;
int greenOffset1 = BYTES_PER_PIXEL + 1;
int childStep = 2 * HeightfieldData::COLOR_BYTES;
int redOffset3 = childStride + HeightfieldData::COLOR_BYTES;
int greenOffset1 = HeightfieldData::COLOR_BYTES + 1;
int greenOffset2 = childStride + 1;
int greenOffset3 = childStride + BYTES_PER_PIXEL + 1;
int blueOffset1 = BYTES_PER_PIXEL + 2;
int greenOffset3 = childStride + HeightfieldData::COLOR_BYTES + 1;
int blueOffset1 = HeightfieldData::COLOR_BYTES + 2;
int blueOffset2 = childStride + 2;
int blueOffset3 = childStride + BYTES_PER_PIXEL + 2;
int blueOffset3 = childStride + HeightfieldData::COLOR_BYTES + 2;
if (childSize == size) {
// simple case: one destination value for four child values
for (int z = 0; z < halfSize; z++) {
for (char* end = dest + halfSize * BYTES_PER_PIXEL; dest != end; src += childStep) {
*dest++ = ((int)src[0] + (int)src[BYTES_PER_PIXEL] + (int)src[childStride] + (int)src[redOffset3]) >> 2;
for (char* end = dest + halfSize * HeightfieldData::COLOR_BYTES; dest != end; src += childStep) {
*dest++ = ((int)src[0] + (int)src[HeightfieldData::COLOR_BYTES] +
(int)src[childStride] + (int)src[redOffset3]) >> 2;
*dest++ = ((int)src[1] + (int)src[greenOffset1] + (int)src[greenOffset2] + (int)src[greenOffset3]) >> 2;
*dest++ = ((int)src[2] + (int)src[blueOffset1] + (int)src[blueOffset2] + (int)src[blueOffset3]) >> 2;
}
@ -904,13 +902,14 @@ bool HeightfieldColorAttribute::merge(void*& parent, void* children[], bool post
int halfChildSize = childSize / 2;
int destPerSrc = size / childSize;
for (int z = 0; z < halfChildSize; z++) {
for (uchar* end = src + childSize * BYTES_PER_PIXEL; src != end; src += childStep) {
*dest++ = ((int)src[0] + (int)src[BYTES_PER_PIXEL] + (int)src[childStride] + (int)src[redOffset3]) >> 2;
for (uchar* end = src + childSize * HeightfieldData::COLOR_BYTES; src != end; src += childStep) {
*dest++ = ((int)src[0] + (int)src[HeightfieldData::COLOR_BYTES] +
(int)src[childStride] + (int)src[redOffset3]) >> 2;
*dest++ = ((int)src[1] + (int)src[greenOffset1] + (int)src[greenOffset2] + (int)src[greenOffset3]) >> 2;
*dest++ = ((int)src[2] + (int)src[blueOffset1] + (int)src[blueOffset2] + (int)src[blueOffset3]) >> 2;
for (int j = 1; j < destPerSrc; j++) {
memcpy(dest, dest - BYTES_PER_PIXEL, BYTES_PER_PIXEL);
dest += BYTES_PER_PIXEL;
memcpy(dest, dest - HeightfieldData::COLOR_BYTES, HeightfieldData::COLOR_BYTES);
dest += HeightfieldData::COLOR_BYTES;
}
}
dest += halfStride;

View file

@ -428,6 +428,8 @@ typedef QExplicitlySharedDataPointer<HeightfieldData> HeightfieldDataPointer;
class HeightfieldData : public QSharedData {
public:
static const int COLOR_BYTES = 3;
HeightfieldData(const QByteArray& contents);
HeightfieldData(Bitstream& in, int bytes, bool color);
HeightfieldData(Bitstream& in, int bytes, const HeightfieldDataPointer& reference, bool color);