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); 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*)&heightID);
glDeleteTextures(1, (GLuint*)&colorID); glDeleteTextures(1, (GLuint*)&colorID);
glDeleteTextures(1, (GLuint*)&textureID);
} }
MetavoxelClient* MetavoxelSystem::createClient(const SharedNodePointer& node) { 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; const int HeightfieldBuffer::HEIGHT_EXTENSION = 2 * HeightfieldBuffer::HEIGHT_BORDER + HeightfieldBuffer::SHARED_EDGE;
HeightfieldBuffer::HeightfieldBuffer(const glm::vec3& translation, float scale, 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), _translation(translation),
_scale(scale), _scale(scale),
_heightBounds(translation, translation + glm::vec3(scale, scale, scale)), _heightBounds(translation, translation + glm::vec3(scale, scale, scale)),
_colorBounds(_heightBounds), _colorBounds(_heightBounds),
_textureBounds(_heightBounds),
_height(height), _height(height),
_color(color), _color(color),
_texture(texture),
_heightTextureID(0), _heightTextureID(0),
_colorTextureID(0), _colorTextureID(0),
_textureTextureID(0),
_heightSize(glm::sqrt(height.size())), _heightSize(glm::sqrt(height.size())),
_heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)), _heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),
_colorSize(glm::sqrt(color.size() / HeightfieldData::COLOR_BYTES)), _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.x -= _heightIncrement * HEIGHT_BORDER;
_heightBounds.minimum.z -= _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.x += _colorIncrement * SHARED_EDGE;
_colorBounds.maximum.z += _colorIncrement * SHARED_EDGE; _colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;
_textureBounds.maximum.x += _textureIncrement * SHARED_EDGE;
_textureBounds.maximum.z += _textureIncrement * SHARED_EDGE;
} }
HeightfieldBuffer::~HeightfieldBuffer() { HeightfieldBuffer::~HeightfieldBuffer() {
// the textures have to be deleted on the main thread (for its opengl context) // the textures have to be deleted on the main thread (for its opengl context)
if (QThread::currentThread() != Application::getInstance()->thread()) { if (QThread::currentThread() != Application::getInstance()->thread()) {
QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", 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 { } else {
glDeleteTextures(1, &_heightTextureID); glDeleteTextures(1, &_heightTextureID);
glDeleteTextures(1, &_colorTextureID); glDeleteTextures(1, &_colorTextureID);
glDeleteTextures(1, &_textureTextureID);
} }
} }
@ -692,6 +702,17 @@ void HeightfieldBuffer::render(bool cursor) {
int colorSize = glm::sqrt(_color.size() / HeightfieldData::COLOR_BYTES); 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()); 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 // create the buffer objects lazily
int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER; int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER;
@ -998,7 +1019,8 @@ private:
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()->getHeightfieldTextureAttribute(), QVector<AttributePointer>(), lod),
_intersections(intersections) { _intersections(intersections) {
} }
@ -1065,11 +1087,11 @@ int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
int colorSize = _buffer->getColorSize(); int colorSize = _buffer->getColorSize();
if (colorSize == 0) { if (colorSize == 0) {
return STOP_RECURSION; continue;
} }
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>(); HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
if (!color) { if (!color) {
return STOP_RECURSION; continue;
} }
const Box& colorBounds = _buffer->getColorBounds(); const Box& colorBounds = _buffer->getColorBounds();
overlap = colorBounds.getIntersection(overlap); 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; return STOP_RECURSION;
} }
@ -1138,6 +1204,7 @@ private:
HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) : HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() << MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() << AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
AttributeRegistry::getInstance()->getHeightfieldTextureAttribute() <<
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)),
@ -1165,18 +1232,28 @@ int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
colorContentsSize = extendedColorSize * extendedColorSize * HeightfieldData::COLOR_BYTES; 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*>( 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(); Box bounds = info.getBounds();
if (existingBuffer && existingBuffer->getHeight().size() == heightContentsSize && 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 // we already have a buffer of the correct resolution
addRegion(bounds, existingBuffer->getHeightBounds()); addRegion(bounds, existingBuffer->getHeightBounds());
return STOP_RECURSION; return STOP_RECURSION;
} }
// 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)); QByteArray(colorContentsSize, 0), QByteArray(textureContentsSize, 0));
const Box& heightBounds = buffer->getHeightBounds(); const Box& heightBounds = buffer->getHeightBounds();
addRegion(bounds, heightBounds); addRegion(bounds, heightBounds);
@ -1249,7 +1326,7 @@ int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {
return STOP_RECURSION; return STOP_RECURSION;
} }
HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size, HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,
buffer->getHeight(), buffer->getColor()); buffer->getHeight(), buffer->getColor(), buffer->getTexture());
_fetchVisitor.init(newBuffer); _fetchVisitor.init(newBuffer);
_data->guide(_fetchVisitor); _data->guide(_fetchVisitor);
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(BufferDataPointer(newBuffer))); 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 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: protected:
@ -139,7 +139,8 @@ public:
static const int SHARED_EDGE; static const int SHARED_EDGE;
static const int HEIGHT_EXTENSION; 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(); ~HeightfieldBuffer();
const glm::vec3& getTranslation() const { return _translation; } const glm::vec3& getTranslation() const { return _translation; }
@ -147,6 +148,7 @@ public:
const Box& getHeightBounds() const { return _heightBounds; } const Box& getHeightBounds() const { return _heightBounds; }
const Box& getColorBounds() const { return _colorBounds; } const Box& getColorBounds() const { return _colorBounds; }
const Box& getTextureBounds() const { return _textureBounds; }
QByteArray& getHeight() { return _height; } QByteArray& getHeight() { return _height; }
const QByteArray& getHeight() const { return _height; } const QByteArray& getHeight() const { return _height; }
@ -154,6 +156,9 @@ public:
QByteArray& getColor() { return _color; } QByteArray& getColor() { return _color; }
const QByteArray& getColor() const { return _color; } const QByteArray& getColor() const { return _color; }
QByteArray& getTexture() { return _texture; }
const QByteArray& getTexture() const { return _texture; }
QByteArray getUnextendedHeight() const; QByteArray getUnextendedHeight() const;
QByteArray getUnextendedColor() const; QByteArray getUnextendedColor() const;
@ -163,6 +168,9 @@ public:
int getColorSize() const { return _colorSize; } int getColorSize() const { return _colorSize; }
float getColorIncrement() const { return _colorIncrement; } float getColorIncrement() const { return _colorIncrement; }
int getTextureSize() const { return _textureSize; }
float getTextureIncrement() const { return _textureIncrement; }
virtual void render(bool cursor = false); virtual void render(bool cursor = false);
private: private:
@ -171,15 +179,20 @@ private:
float _scale; float _scale;
Box _heightBounds; Box _heightBounds;
Box _colorBounds; Box _colorBounds;
Box _textureBounds;
QByteArray _height; QByteArray _height;
QByteArray _color; QByteArray _color;
QByteArray _texture;
GLuint _heightTextureID; GLuint _heightTextureID;
GLuint _colorTextureID; GLuint _colorTextureID;
GLuint _textureTextureID;
int _heightSize; int _heightSize;
float _heightIncrement; float _heightIncrement;
int _colorSize; int _colorSize;
float _colorIncrement; float _colorIncrement;
int _textureSize;
float _textureIncrement;
typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair; typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair;
static QHash<int, BufferPair> _bufferPairs; static QHash<int, BufferPair> _bufferPairs;
}; };

View file

@ -1049,7 +1049,8 @@ void ImportHeightfieldTool::updatePreview() {
columns * HeightfieldData::COLOR_BYTES); 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())));
} }
} }
} }