Yet more texture bits.

This commit is contained in:
Andrzej Kapolka 2014-08-19 18:55:18 -07:00
parent 540d074270
commit 7cf7f188f8
3 changed files with 106 additions and 15 deletions

View file

@ -449,9 +449,10 @@ void MetavoxelSystem::renderHeightfieldCursor(const glm::vec3& position, float r
glDepthFunc(GL_LESS);
}
void MetavoxelSystem::deleteTextures(int heightID, int colorID) {
void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) {
glDeleteTextures(1, (GLuint*)&heightID);
glDeleteTextures(1, (GLuint*)&colorID);
glDeleteTextures(1, (GLuint*)&textureID);
}
MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) {
@ -601,19 +602,24 @@ const int HeightfieldBuffer::SHARED_EDGE = 1;
const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE;
HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,
const QByteArray& height, const QByteArray& color) :
const QByteArray& height, const QByteArray& color, const QByteArray& texture) :
_translation(translation),
_scale(scale),
_heightBounds(translation, translation + glm::vec3(scale, scale, scale)),
_colorBounds(_heightBounds),
_textureBounds(_heightBounds),
_height(height),
_color(color),
_texture(texture),
_heightTextureID(0),
_colorTextureID(0),
_textureTextureID(0),
_heightSize(glm::sqrt(height.size())),
_heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),
_colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)),
_colorIncrement(scale / (_colorSize - SHARED_EDGE)) {
_colorIncrement(scale / (_colorSize - SHARED_EDGE)),
_textureSize(glm::sqrt(texture.size())),
_textureIncrement(scale / (_textureSize - SHARED_EDGE)) {
_heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER;
_heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER;
@ -622,16 +628,20 @@ HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale,
_colorBounds.maximum.x += _colorIncrement * SHARED_EDGE;
_colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;
_textureBounds.maximum.x += _textureIncrement * SHARED_EDGE;
_textureBounds.maximum.z += _textureIncrement * SHARED_EDGE;
}
HeightfieldBuffer::~HeightfieldBuffer() {
// the textures have to be deleted on the main thread (for its opengl context)
if (QThread::currentThread() != Application::getInstance()->thread()) {
QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures",
Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID));
Q_ARG(int, _heightTextureID), Q_ARG(int, _colorTextureID), Q_ARG(int, _textureTextureID));
} else {
glDeleteTextures(1, &_heightTextureID);
glDeleteTextures(1, &_colorTextureID);
glDeleteTextures(1, &_textureTextureID);
}
}
@ -692,6 +702,17 @@ void HeightfieldBuffer::render(bool cursor) {
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 (!_texture.isEmpty()) {
glGenTextures(1, &_textureTextureID);
glBindTexture(GL_TEXTURE_2D, _textureTextureID);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
int textureSize = glm::sqrt(_texture.size());
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, textureSize, textureSize, 0,
GL_LUMINANCE, GL_UNSIGNED_BYTE, _texture.constData());
}
}
// create the buffer objects lazily
int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER;
@ -998,7 +1019,8 @@ private:
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()->getHeightfieldTextureAttribute(), QVector<AttributePointer>(), lod),
_intersections(intersections) {
}
@ -1065,11 +1087,11 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
int colorSize = _buffer->getColorSize();
if (colorSize == 0) {
return STOP_RECURSION;
continue;
}
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
if (!color) {
return STOP_RECURSION;
continue;
}
const Box& colorBounds = _buffer->getColorBounds();
overlap = colorBounds.getIntersection(overlap);
@ -1113,6 +1135,50 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
}
}
}
int textureSize = _buffer->getTextureSize();
if (textureSize == 0) {
continue;
}
HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue<HeightfieldTextureDataPointer>();
if (!texture) {
continue;
}
const Box& textureBounds = _buffer->getTextureBounds();
overlap = textureBounds.getIntersection(overlap);
float textureIncrement = _buffer->getTextureIncrement();
destX = (overlap.minimum.x - textureBounds.minimum.x) / textureIncrement;
destY = (overlap.minimum.z - textureBounds.minimum.z) / textureIncrement;
destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / textureIncrement);
destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / textureIncrement);
dest = _buffer->getTexture().data() + destY * textureSize + destX;
const QByteArray& srcTexture = texture->getContents();
srcSize = glm::sqrt(srcTexture.size());
srcIncrement = info.size / srcSize;
if (srcIncrement == textureIncrement) {
// 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 = srcTexture.constData() + srcY * srcSize + srcX;
for (int y = 0; y < destHeight; y++, src += srcSize, dest += textureSize) {
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 = textureIncrement / srcIncrement;
for (int y = 0; y < destHeight; y++, dest += textureSize, srcY += srcAdvance) {
const char* src = srcTexture.constData() + (int)srcY * srcSize;
float lineSrcX = srcX;
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
*lineDest = src[(int)lineSrcX];
}
}
}
}
return STOP_RECURSION;
}
@ -1138,6 +1204,7 @@ private:
HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldTextureAttribute() <<
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)),
@ -1165,18 +1232,28 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES;
}
HeightfieldTextureDataPointer texture = info.inputValues.at(2).getInlineValue<HeightfieldTextureDataPointer>();
int textureContentsSize = 0;
if (texture) {
const QByteArray& textureContents = texture->getContents();
int textureSize = glm::sqrt(textureContents.size());
int extendedTextureSize = textureSize + HeightfieldBuffer::SHARED_EDGE;
textureContentsSize = extendedTextureSize * extendedTextureSize;
}
const HeightfieldBuffer* existingBuffer = static_cast<const HeightfieldBuffer*>(
info.inputValues.at(2).getInlineValue<BufferDataPointer>().data());
info.inputValues.at(3).getInlineValue<BufferDataPointer>().data());
Box bounds = info.getBounds();
if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize &&
existingBuffer->getColor().size() == colorContentsSize) {
existingBuffer->getColor().size() == colorContentsSize &&
existingBuffer->getTexture().size() == textureContentsSize) {
// 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));
QByteArray(colorContentsSize, 0), QByteArray(textureContentsSize, 0));
const Box& heightBounds = buffer->getHeightBounds();
addRegion(bounds, heightBounds);
@ -1249,7 +1326,7 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {
return STOP_RECURSION;
}
HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,
buffer->getHeight(), buffer->getColor());
buffer->getHeight(), buffer->getColor(), buffer->getTexture());
_fetchVisitor.init(newBuffer);
_data->guide(_fetchVisitor);
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer)));

View file

@ -49,7 +49,7 @@ public:
Q_INVOKABLE float getHeightfieldHeight(const glm::vec3& location);
Q_INVOKABLE void deleteTextures(int heightID, int colorID);
Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID);
protected:
@ -139,7 +139,8 @@ public:
static const int SHARED_EDGE;
static const int HEIGHT_EXTENSION;
HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height, const QByteArray& color);
HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height,
const QByteArray& color, const QByteArray& texture);
~HeightfieldBuffer();
const glm::vec3& getTranslation() const { return _translation; }
@ -147,6 +148,7 @@ public:
const Box& getHeightBounds() const { return _heightBounds; }
const Box& getColorBounds() const { return _colorBounds; }
const Box& getTextureBounds() const { return _textureBounds; }
QByteArray& getHeight() { return _height; }
const QByteArray& getHeight() const { return _height; }
@ -154,6 +156,9 @@ public:
QByteArray& getColor() { return _color; }
const QByteArray& getColor() const { return _color; }
QByteArray& getTexture() { return _texture; }
const QByteArray& getTexture() const { return _texture; }
QByteArray getUnextendedHeight() const;
QByteArray getUnextendedColor() const;
@ -163,6 +168,9 @@ public:
int getColorSize() const { return _colorSize; }
float getColorIncrement() const { return _colorIncrement; }
int getTextureSize() const { return _textureSize; }
float getTextureIncrement() const { return _textureIncrement; }
virtual void render(bool cursor = false);
private:
@ -171,15 +179,20 @@ private:
float _scale;
Box _heightBounds;
Box _colorBounds;
Box _textureBounds;
QByteArray _height;
QByteArray _color;
QByteArray _texture;
GLuint _heightTextureID;
GLuint _colorTextureID;
GLuint _textureTextureID;
int _heightSize;
float _heightIncrement;
int _colorSize;
float _colorIncrement;
int _textureSize;
float _textureIncrement;
typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair;
static QHash<int, BufferPair> _bufferPairs;
};

View file

@ -1049,7 +1049,8 @@ void ImportHeightfieldTool::updatePreview() {
columns * HeightfieldData::COLOR_BYTES);
}
}
buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f, height, color)));
buffers.append(BufferDataPointer(new HeightfieldBuffer(glm::vec3(x, 0.0f, z), 1.0f,
height, color, QByteArray())));
}
}
}