mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 14:03:55 +02:00
Removed heightfield buffer code.
This commit is contained in:
parent
bba042e823
commit
479bea1eb2
2 changed files with 9 additions and 914 deletions
|
@ -58,11 +58,6 @@ void MetavoxelSystem::init() {
|
|||
MetavoxelClientManager::init();
|
||||
DefaultMetavoxelRendererImplementation::init();
|
||||
|
||||
_heightfieldBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
|
||||
new BufferDataAttribute("heightfieldBuffer"));
|
||||
_heightfieldBufferAttribute->setLODThresholdMultiplier(
|
||||
AttributeRegistry::getInstance()->getHeightfieldAttribute()->getLODThresholdMultiplier());
|
||||
|
||||
_voxelBufferAttribute = AttributeRegistry::getInstance()->registerAttribute(
|
||||
new BufferDataAttribute("voxelBuffer"));
|
||||
_voxelBufferAttribute->setLODThresholdMultiplier(
|
||||
|
@ -375,12 +370,6 @@ void MetavoxelSystem::renderVoxelCursor(const glm::vec3& position, float radius)
|
|||
glDepthFunc(GL_LESS);
|
||||
}
|
||||
|
||||
void MetavoxelSystem::deleteTextures(int heightID, int colorID, int textureID) {
|
||||
glDeleteTextures(1, (GLuint*)&heightID);
|
||||
glDeleteTextures(1, (GLuint*)&colorID);
|
||||
glDeleteTextures(1, (GLuint*)&textureID);
|
||||
}
|
||||
|
||||
class MaterialEditApplier : public SignalHandler {
|
||||
public:
|
||||
|
||||
|
@ -670,357 +659,12 @@ void MetavoxelSystemClient::sendDatagram(const QByteArray& data) {
|
|||
BufferData::~BufferData() {
|
||||
}
|
||||
|
||||
const int HeightfieldBuffer::HEIGHT_BORDER = 1;
|
||||
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& material,
|
||||
const QVector<SharedObjectPointer>& materials) :
|
||||
_translation(translation),
|
||||
_scale(scale),
|
||||
_heightBounds(translation, translation + glm::vec3(scale, scale, scale)),
|
||||
_colorBounds(_heightBounds),
|
||||
_materialBounds(_heightBounds),
|
||||
_height(height),
|
||||
_color(color),
|
||||
_material(material),
|
||||
_materials(materials),
|
||||
_heightTextureID(0),
|
||||
_colorTextureID(0),
|
||||
_materialTextureID(0),
|
||||
_heightSize(glm::sqrt((float)height.size())),
|
||||
_heightIncrement(scale / (_heightSize - HEIGHT_EXTENSION)),
|
||||
_colorSize(glm::sqrt((float)color.size() / DataBlock::COLOR_BYTES)),
|
||||
_colorIncrement(scale / (_colorSize - SHARED_EDGE)),
|
||||
_materialSize(glm::sqrt((float)material.size())),
|
||||
_materialIncrement(scale / (_materialSize - SHARED_EDGE)) {
|
||||
|
||||
_heightBounds.minimum.x -= _heightIncrement * HEIGHT_BORDER;
|
||||
_heightBounds.minimum.z -= _heightIncrement * HEIGHT_BORDER;
|
||||
_heightBounds.maximum.x += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
|
||||
_heightBounds.maximum.z += _heightIncrement * (SHARED_EDGE + HEIGHT_BORDER);
|
||||
|
||||
_colorBounds.maximum.x += _colorIncrement * SHARED_EDGE;
|
||||
_colorBounds.maximum.z += _colorIncrement * SHARED_EDGE;
|
||||
|
||||
_materialBounds.maximum.x += _materialIncrement * SHARED_EDGE;
|
||||
_materialBounds.maximum.z += _materialIncrement * 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, _materialTextureID));
|
||||
} else {
|
||||
glDeleteTextures(1, &_heightTextureID);
|
||||
glDeleteTextures(1, &_colorTextureID);
|
||||
glDeleteTextures(1, &_materialTextureID);
|
||||
}
|
||||
}
|
||||
|
||||
QByteArray HeightfieldBuffer::getUnextendedHeight() const {
|
||||
int srcSize = glm::sqrt(float(_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(int x, int y) const {
|
||||
int unextendedSize = _heightSize - HEIGHT_EXTENSION;
|
||||
QByteArray unextended(unextendedSize * unextendedSize * DataBlock::COLOR_BYTES, 0);
|
||||
char* dest = unextended.data();
|
||||
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;
|
||||
}
|
||||
|
||||
class HeightfieldPoint {
|
||||
public:
|
||||
glm::vec2 textureCoord;
|
||||
glm::vec3 vertex;
|
||||
};
|
||||
|
||||
const int SPLAT_COUNT = 4;
|
||||
const GLint SPLAT_TEXTURE_UNITS[] = { 3, 4, 5, 6 };
|
||||
|
||||
static const int EIGHT_BIT_MAXIMUM = 255;
|
||||
static const float EIGHT_BIT_MAXIMUM_RECIPROCAL = 1.0f / EIGHT_BIT_MAXIMUM;
|
||||
|
||||
void HeightfieldBuffer::render(bool cursor) {
|
||||
// initialize textures, etc. on first render
|
||||
if (_heightTextureID == 0) {
|
||||
glGenTextures(1, &_heightTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _heightTextureID);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
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());
|
||||
|
||||
glGenTextures(1, &_colorTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
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);
|
||||
if (_color.isEmpty()) {
|
||||
const quint8 WHITE_COLOR[] = { 255, 255, 255 };
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, 1, 1, 0, GL_RGB, GL_UNSIGNED_BYTE, WHITE_COLOR);
|
||||
|
||||
} else {
|
||||
int colorSize = glm::sqrt(float(_color.size() / DataBlock::COLOR_BYTES));
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, colorSize, colorSize, 0, GL_RGB, GL_UNSIGNED_BYTE, _color.constData());
|
||||
}
|
||||
|
||||
if (!_material.isEmpty()) {
|
||||
glGenTextures(1, &_materialTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _materialTextureID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
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 materialSize = glm::sqrt(float(_material.size()));
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, materialSize, materialSize, 0,
|
||||
GL_LUMINANCE, GL_UNSIGNED_BYTE, _material.constData());
|
||||
|
||||
_networkTextures.resize(_materials.size());
|
||||
for (int i = 0; i < _materials.size(); i++) {
|
||||
const SharedObjectPointer material = _materials.at(i);
|
||||
if (material) {
|
||||
_networkTextures[i] = Application::getInstance()->getTextureCache()->getTexture(
|
||||
static_cast<MaterialObject*>(material.data())->getDiffuse(), SPLAT_TEXTURE);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// create the buffer objects lazily
|
||||
int innerSize = _heightSize - 2 * HeightfieldBuffer::HEIGHT_BORDER;
|
||||
int vertexCount = _heightSize * _heightSize;
|
||||
int rows = _heightSize - 1;
|
||||
int indexCount = rows * rows * 3 * 2;
|
||||
BufferPair& bufferPair = _bufferPairs[_heightSize];
|
||||
if (!bufferPair.first.isCreated()) {
|
||||
QVector<HeightfieldPoint> vertices(vertexCount);
|
||||
HeightfieldPoint* point = vertices.data();
|
||||
|
||||
float vertexStep = 1.0f / (innerSize - 1);
|
||||
float z = -vertexStep;
|
||||
float textureStep = 1.0f / _heightSize;
|
||||
float t = textureStep / 2.0f;
|
||||
for (int i = 0; i < _heightSize; i++, z += vertexStep, t += textureStep) {
|
||||
float x = -vertexStep;
|
||||
float s = textureStep / 2.0f;
|
||||
const float SKIRT_LENGTH = 0.25f;
|
||||
float baseY = (i == 0 || i == _heightSize - 1) ? -SKIRT_LENGTH : 0.0f;
|
||||
for (int j = 0; j < _heightSize; j++, point++, x += vertexStep, s += textureStep) {
|
||||
point->vertex = glm::vec3(x, (j == 0 || j == _heightSize - 1) ? -SKIRT_LENGTH : baseY, z);
|
||||
point->textureCoord = glm::vec2(s, t);
|
||||
}
|
||||
}
|
||||
|
||||
bufferPair.first.setUsagePattern(QOpenGLBuffer::StaticDraw);
|
||||
bufferPair.first.create();
|
||||
bufferPair.first.bind();
|
||||
bufferPair.first.allocate(vertices.constData(), vertexCount * sizeof(HeightfieldPoint));
|
||||
|
||||
QVector<int> indices(indexCount);
|
||||
int* index = indices.data();
|
||||
for (int i = 0; i < rows; i++) {
|
||||
int lineIndex = i * _heightSize;
|
||||
int nextLineIndex = (i + 1) * _heightSize;
|
||||
for (int j = 0; j < rows; j++) {
|
||||
*index++ = lineIndex + j;
|
||||
*index++ = nextLineIndex + j;
|
||||
*index++ = nextLineIndex + j + 1;
|
||||
|
||||
*index++ = nextLineIndex + j + 1;
|
||||
*index++ = lineIndex + j + 1;
|
||||
*index++ = lineIndex + j;
|
||||
}
|
||||
}
|
||||
|
||||
bufferPair.second = QOpenGLBuffer(QOpenGLBuffer::IndexBuffer);
|
||||
bufferPair.second.create();
|
||||
bufferPair.second.bind();
|
||||
bufferPair.second.allocate(indices.constData(), indexCount * sizeof(int));
|
||||
|
||||
} else {
|
||||
bufferPair.first.bind();
|
||||
bufferPair.second.bind();
|
||||
}
|
||||
|
||||
HeightfieldPoint* point = 0;
|
||||
glVertexPointer(3, GL_FLOAT, sizeof(HeightfieldPoint), &point->vertex);
|
||||
glTexCoordPointer(2, GL_FLOAT, sizeof(HeightfieldPoint), &point->textureCoord);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(_translation.x, _translation.y, _translation.z);
|
||||
glScalef(_scale, _scale, _scale);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _heightTextureID);
|
||||
|
||||
if (cursor) {
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
} else if (!_materials.isEmpty()) {
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize);
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
|
||||
DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
glDepthMask(false);
|
||||
glEnable(GL_BLEND);
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glEnable(GL_POLYGON_OFFSET_FILL);
|
||||
glPolygonOffset(-1.0f, -1.0f);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().bind();
|
||||
const DefaultMetavoxelRendererImplementation::SplatLocations& locations =
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldLocations();
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.heightScale, 1.0f / _heightSize);
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.textureScale, (float)_heightSize / innerSize);
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.splatTextureOffset, _translation.x / _scale, _translation.z / _scale);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, _materialTextureID);
|
||||
|
||||
for (int i = 0; i < _materials.size(); i += SPLAT_COUNT) {
|
||||
QVector4D scalesS, scalesT;
|
||||
|
||||
for (int j = 0; j < SPLAT_COUNT; j++) {
|
||||
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[j]);
|
||||
int index = i + j;
|
||||
if (index < _networkTextures.size()) {
|
||||
const NetworkTexturePointer& texture = _networkTextures.at(index);
|
||||
if (texture) {
|
||||
MaterialObject* material = static_cast<MaterialObject*>(_materials.at(index).data());
|
||||
scalesS[j] = _scale / material->getScaleS();
|
||||
scalesT[j] = _scale / material->getScaleT();
|
||||
glBindTexture(GL_TEXTURE_2D, texture->getID());
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
} else {
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
}
|
||||
const float QUARTER_STEP = 0.25f * EIGHT_BIT_MAXIMUM_RECIPROCAL;
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.splatTextureScalesS, scalesS);
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.splatTextureScalesT, scalesT);
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.textureValueMinima,
|
||||
(i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP,
|
||||
(i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL - QUARTER_STEP);
|
||||
DefaultMetavoxelRendererImplementation::getSplatHeightfieldProgram().setUniformValue(
|
||||
locations.textureValueMaxima,
|
||||
(i + 1) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 2) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP,
|
||||
(i + 3) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP, (i + 4) * EIGHT_BIT_MAXIMUM_RECIPROCAL + QUARTER_STEP);
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
for (int i = 0; i < SPLAT_COUNT; i++) {
|
||||
glActiveTexture(GL_TEXTURE0 + SPLAT_TEXTURE_UNITS[i]);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
}
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
glDisable(GL_POLYGON_OFFSET_FILL);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glDisable(GL_BLEND);
|
||||
glDepthMask(true);
|
||||
glDepthFunc(GL_LESS);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
|
||||
|
||||
} else {
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightScaleLocation(), 1.0f / _heightSize);
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().setUniformValue(
|
||||
DefaultMetavoxelRendererImplementation::getBaseColorScaleLocation(), (float)_heightSize / innerSize);
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
|
||||
glDrawRangeElements(GL_TRIANGLES, 0, vertexCount - 1, indexCount, GL_UNSIGNED_INT, 0);
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
}
|
||||
|
||||
glBindTexture(GL_TEXTURE_2D, 0);
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
bufferPair.first.release();
|
||||
bufferPair.second.release();
|
||||
}
|
||||
|
||||
QHash<int, HeightfieldBuffer::BufferPair> HeightfieldBuffer::_bufferPairs;
|
||||
|
||||
void HeightfieldPreview::render(const glm::vec3& translation, float scale) const {
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, true);
|
||||
|
||||
glDisable(GL_BLEND);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_ALPHA_TEST);
|
||||
glAlphaFunc(GL_EQUAL, 0.0f);
|
||||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
glEnableClientState(GL_VERTEX_ARRAY);
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().bind();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(translation.x, translation.y, translation.z);
|
||||
glScalef(scale, scale, scale);
|
||||
|
||||
foreach (const BufferDataPointer& buffer, _buffers) {
|
||||
buffer->render();
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
DefaultMetavoxelRendererImplementation::getBaseHeightfieldProgram().release();
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
glDisableClientState(GL_VERTEX_ARRAY);
|
||||
|
||||
glDisable(GL_ALPHA_TEST);
|
||||
glDisable(GL_CULL_FACE);
|
||||
glEnable(GL_BLEND);
|
||||
|
||||
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
|
||||
}
|
||||
|
||||
void VoxelPoint::setNormal(const glm::vec3& normal) {
|
||||
this->normal[0] = (char)(normal.x * 127.0f);
|
||||
this->normal[1] = (char)(normal.y * 127.0f);
|
||||
|
@ -1344,446 +988,6 @@ void DefaultMetavoxelRendererImplementation::init() {
|
|||
DefaultMetavoxelRendererImplementation::DefaultMetavoxelRendererImplementation() {
|
||||
}
|
||||
|
||||
class HeightfieldFetchVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections);
|
||||
|
||||
void init(HeightfieldBuffer* buffer);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
const QVector<Box>& _intersections;
|
||||
HeightfieldBuffer* _buffer;
|
||||
|
||||
QVector<int> _depthFlags;
|
||||
};
|
||||
|
||||
enum DepthFlags { HEIGHT_FLAG = 0x01, COLOR_FLAG = 0x02, MATERIAL_FLAG = 0x04 };
|
||||
|
||||
HeightfieldFetchVisitor::HeightfieldFetchVisitor(const MetavoxelLOD& lod, const QVector<Box>& intersections) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute(), QVector<AttributePointer>(), lod),
|
||||
_intersections(intersections) {
|
||||
}
|
||||
|
||||
void HeightfieldFetchVisitor::init(HeightfieldBuffer* buffer) {
|
||||
_buffer = buffer;
|
||||
}
|
||||
|
||||
int HeightfieldFetchVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_buffer->getHeightBounds())) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (_depthFlags.size() > _depth) {
|
||||
_depthFlags[_depth] = 0;
|
||||
} else {
|
||||
_depthFlags.append(0);
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
postVisit(info);
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool HeightfieldFetchVisitor::postVisit(MetavoxelInfo& info) {
|
||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||
int flags = _depthFlags.at(_depth);
|
||||
if (height) {
|
||||
// to handle borders correctly, make sure we only sample nodes with resolution <= ours
|
||||
int heightSize = glm::sqrt((float)height->getContents().size());
|
||||
float heightIncrement = info.size / heightSize;
|
||||
if (heightIncrement < _buffer->getHeightIncrement() || (flags & HEIGHT_FLAG)) {
|
||||
height.reset();
|
||||
} else {
|
||||
flags |= HEIGHT_FLAG;
|
||||
}
|
||||
}
|
||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
if (color) {
|
||||
int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);
|
||||
float colorIncrement = info.size / colorSize;
|
||||
if (colorIncrement < _buffer->getColorIncrement() || (flags & COLOR_FLAG)) {
|
||||
color.reset();
|
||||
} else {
|
||||
flags |= COLOR_FLAG;
|
||||
}
|
||||
}
|
||||
HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
||||
if (material) {
|
||||
int materialSize = glm::sqrt((float)material->getContents().size());
|
||||
float materialIncrement = info.size / materialSize;
|
||||
if (materialIncrement < _buffer->getMaterialIncrement() || (flags & MATERIAL_FLAG)) {
|
||||
material.reset();
|
||||
} else {
|
||||
flags |= MATERIAL_FLAG;
|
||||
}
|
||||
}
|
||||
if (_depth > 0) {
|
||||
_depthFlags[_depth - 1] |= flags;
|
||||
}
|
||||
if (!(height || color || material)) {
|
||||
return false;
|
||||
}
|
||||
Box bounds = info.getBounds();
|
||||
foreach (const Box& intersection, _intersections) {
|
||||
Box overlap = intersection.getIntersection(bounds);
|
||||
if (overlap.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
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 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) {
|
||||
const Box& materialBounds = _buffer->getMaterialBounds();
|
||||
overlap = materialBounds.getIntersection(overlap);
|
||||
float materialIncrement = _buffer->getMaterialIncrement();
|
||||
int destX = (overlap.minimum.x - materialBounds.minimum.x) / materialIncrement;
|
||||
int destY = (overlap.minimum.z - materialBounds.minimum.z) / materialIncrement;
|
||||
int destWidth = glm::ceil((overlap.maximum.x - overlap.minimum.x) / materialIncrement);
|
||||
int destHeight = glm::ceil((overlap.maximum.z - overlap.minimum.z) / materialIncrement);
|
||||
int materialSize = _buffer->getMaterialSize();
|
||||
char* dest = _buffer->getMaterial().data() + destY * materialSize + destX;
|
||||
|
||||
const QByteArray& srcMaterial = material->getContents();
|
||||
const QVector<SharedObjectPointer> srcMaterials = material->getMaterials();
|
||||
int srcSize = glm::sqrt((float)srcMaterial.size());
|
||||
float srcIncrement = info.size / srcSize;
|
||||
QHash<int, int> materialMappings;
|
||||
|
||||
if (srcIncrement == materialIncrement) {
|
||||
// easy case: same resolution
|
||||
int srcX = (overlap.minimum.x - info.minimum.x) / srcIncrement;
|
||||
int srcY = (overlap.minimum.z - info.minimum.z) / srcIncrement;
|
||||
|
||||
const uchar* src = (const uchar*)srcMaterial.constData() + srcY * srcSize + srcX;
|
||||
for (int y = 0; y < destHeight; y++, src += srcSize, dest += materialSize) {
|
||||
const uchar* lineSrc = src;
|
||||
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrc++) {
|
||||
int value = *lineSrc;
|
||||
if (value != 0) {
|
||||
int& mapping = materialMappings[value];
|
||||
if (mapping == 0) {
|
||||
mapping = getMaterialIndex(material->getMaterials().at(value - 1),
|
||||
_buffer->getMaterials(), _buffer->getMaterial());
|
||||
}
|
||||
value = mapping;
|
||||
}
|
||||
*lineDest = value;
|
||||
}
|
||||
}
|
||||
} 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 = materialIncrement / srcIncrement;
|
||||
for (int y = 0; y < destHeight; y++, dest += materialSize, srcY += srcAdvance) {
|
||||
const uchar* src = (const uchar*)srcMaterial.constData() + (int)srcY * srcSize;
|
||||
float lineSrcX = srcX;
|
||||
for (char* lineDest = dest, *end = dest + destWidth; lineDest != end; lineDest++, lineSrcX += srcAdvance) {
|
||||
int value = src[(int)lineSrcX];
|
||||
if (value != 0) {
|
||||
int& mapping = materialMappings[value];
|
||||
if (mapping == 0) {
|
||||
mapping = getMaterialIndex(material->getMaterials().at(value - 1),
|
||||
_buffer->getMaterials(), _buffer->getMaterial());
|
||||
}
|
||||
value = mapping;
|
||||
}
|
||||
*lineDest = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
clearUnusedMaterials(_buffer->getMaterials(), _buffer->getMaterial());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
class HeightfieldRegionVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
QVector<Box> regions;
|
||||
Box regionBounds;
|
||||
|
||||
HeightfieldRegionVisitor(const MetavoxelLOD& lod);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
virtual bool postVisit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
void addRegion(const Box& unextended, const Box& extended);
|
||||
|
||||
class DepthInfo {
|
||||
public:
|
||||
float minimumColorIncrement;
|
||||
float minimumMaterialIncrement;
|
||||
|
||||
DepthInfo() : minimumColorIncrement(FLT_MAX), minimumMaterialIncrement(FLT_MAX) { }
|
||||
};
|
||||
|
||||
QVector<DepthInfo> _depthInfo;
|
||||
|
||||
QVector<Box> _intersections;
|
||||
HeightfieldFetchVisitor _fetchVisitor;
|
||||
};
|
||||
|
||||
HeightfieldRegionVisitor::HeightfieldRegionVisitor(const MetavoxelLOD& lod) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getHeightfieldAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldColorAttribute() <<
|
||||
AttributeRegistry::getInstance()->getHeightfieldMaterialAttribute() <<
|
||||
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)),
|
||||
_fetchVisitor(lod, _intersections) {
|
||||
}
|
||||
|
||||
int HeightfieldRegionVisitor::visit(MetavoxelInfo& info) {
|
||||
DepthInfo depthInfo;
|
||||
HeightfieldColorDataPointer color = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
|
||||
if (color) {
|
||||
int colorSize = glm::sqrt((float)color->getContents().size() / DataBlock::COLOR_BYTES);
|
||||
depthInfo.minimumColorIncrement = info.size / colorSize;
|
||||
}
|
||||
HeightfieldMaterialDataPointer material = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
|
||||
if (material) {
|
||||
int materialSize = glm::sqrt((float)material->getContents().size());
|
||||
depthInfo.minimumMaterialIncrement = info.size / materialSize;
|
||||
}
|
||||
if (_depth < _depthInfo.size()) {
|
||||
_depthInfo[_depth] = depthInfo;
|
||||
} else {
|
||||
_depthInfo.append(depthInfo);
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return _visitations.at(_depth).isInputLeaf(0) ? (DEFAULT_ORDER | ALL_NODES_REST) : DEFAULT_ORDER;
|
||||
}
|
||||
postVisit(info);
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
bool HeightfieldRegionVisitor::postVisit(MetavoxelInfo& info) {
|
||||
const DepthInfo& depthInfo = _depthInfo.at(_depth);
|
||||
if (_depth > 0) {
|
||||
DepthInfo& parentDepthInfo = _depthInfo[_depth - 1];
|
||||
parentDepthInfo.minimumColorIncrement = qMin(parentDepthInfo.minimumColorIncrement, depthInfo.minimumColorIncrement);
|
||||
parentDepthInfo.minimumMaterialIncrement = qMin(parentDepthInfo.minimumMaterialIncrement,
|
||||
depthInfo.minimumMaterialIncrement);
|
||||
}
|
||||
if (_visitations.at(_depth).isInputLeaf(0)) {
|
||||
HeightfieldBuffer* buffer = NULL;
|
||||
HeightfieldHeightDataPointer height = info.inputValues.at(0).getInlineValue<HeightfieldHeightDataPointer>();
|
||||
if (height) {
|
||||
int heightSize = glm::sqrt((float)height->getContents().size());
|
||||
int extendedHeightSize = heightSize + HeightfieldBuffer::HEIGHT_EXTENSION;
|
||||
int heightContentsSize = extendedHeightSize * extendedHeightSize;
|
||||
float minimumColorIncrement = depthInfo.minimumColorIncrement;
|
||||
float minimumMaterialIncrement = depthInfo.minimumMaterialIncrement;
|
||||
for (int i = _depth - 1; i >= 0 && qMax(minimumColorIncrement, minimumMaterialIncrement) == FLT_MAX; i--) {
|
||||
const DepthInfo& ancestorDepthInfo = _depthInfo.at(i);
|
||||
minimumColorIncrement = qMin(minimumColorIncrement, ancestorDepthInfo.minimumColorIncrement);
|
||||
minimumMaterialIncrement = qMin(minimumMaterialIncrement, ancestorDepthInfo.minimumMaterialIncrement);
|
||||
}
|
||||
int colorContentsSize = 0;
|
||||
if (minimumColorIncrement != FLT_MAX) {
|
||||
int colorSize = (int)glm::round(info.size / minimumColorIncrement) + HeightfieldBuffer::SHARED_EDGE;
|
||||
colorContentsSize = colorSize * colorSize * DataBlock::COLOR_BYTES;
|
||||
}
|
||||
int materialContentsSize = 0;
|
||||
if (minimumMaterialIncrement != FLT_MAX) {
|
||||
int materialSize = (int)glm::round(info.size / minimumMaterialIncrement) + HeightfieldBuffer::SHARED_EDGE;
|
||||
materialContentsSize = materialSize * materialSize;
|
||||
}
|
||||
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 &&
|
||||
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(), 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), QByteArray(materialContentsSize, 0));
|
||||
const Box& heightBounds = buffer->getHeightBounds();
|
||||
addRegion(bounds, heightBounds);
|
||||
|
||||
_intersections.clear();
|
||||
_intersections.append(Box(heightBounds.minimum,
|
||||
glm::vec3(bounds.maximum.x, heightBounds.maximum.y, bounds.minimum.z)));
|
||||
_intersections.append(Box(glm::vec3(bounds.maximum.x, heightBounds.minimum.y, heightBounds.minimum.z),
|
||||
glm::vec3(heightBounds.maximum.x, heightBounds.maximum.y, bounds.maximum.z)));
|
||||
_intersections.append(Box(glm::vec3(bounds.minimum.x, heightBounds.minimum.y, bounds.maximum.z),
|
||||
heightBounds.maximum));
|
||||
_intersections.append(Box(glm::vec3(heightBounds.minimum.x, heightBounds.minimum.y, bounds.minimum.z),
|
||||
glm::vec3(bounds.minimum.x, heightBounds.maximum.y, heightBounds.maximum.z)));
|
||||
|
||||
_fetchVisitor.init(buffer);
|
||||
_data->guide(_fetchVisitor);
|
||||
}
|
||||
}
|
||||
BufferDataPointer pointer(buffer);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void HeightfieldRegionVisitor::addRegion(const Box& unextended, const Box& extended) {
|
||||
regions.append(unextended);
|
||||
regionBounds.add(extended);
|
||||
}
|
||||
|
||||
class HeightfieldUpdateVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions, const Box& regionBounds);
|
||||
|
||||
virtual int visit(MetavoxelInfo& info);
|
||||
|
||||
private:
|
||||
|
||||
const QVector<Box>& _regions;
|
||||
const Box& _regionBounds;
|
||||
QVector<Box> _intersections;
|
||||
HeightfieldFetchVisitor _fetchVisitor;
|
||||
};
|
||||
|
||||
HeightfieldUpdateVisitor::HeightfieldUpdateVisitor(const MetavoxelLOD& lod, const QVector<Box>& regions,
|
||||
const Box& regionBounds) :
|
||||
MetavoxelVisitor(QVector<AttributePointer>() <<
|
||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), QVector<AttributePointer>() <<
|
||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute(), lod),
|
||||
_regions(regions),
|
||||
_regionBounds(regionBounds),
|
||||
_fetchVisitor(lod, _intersections) {
|
||||
}
|
||||
|
||||
int HeightfieldUpdateVisitor::visit(MetavoxelInfo& info) {
|
||||
if (!info.getBounds().intersects(_regionBounds)) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
if (!info.isLeaf) {
|
||||
return DEFAULT_ORDER;
|
||||
}
|
||||
const HeightfieldBuffer* buffer = static_cast<const HeightfieldBuffer*>(
|
||||
info.inputValues.at(0).getInlineValue<BufferDataPointer>().data());
|
||||
if (!buffer) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
_intersections.clear();
|
||||
foreach (const Box& region, _regions) {
|
||||
if (region.intersects(buffer->getHeightBounds())) {
|
||||
_intersections.append(region.getIntersection(buffer->getHeightBounds()));
|
||||
}
|
||||
}
|
||||
if (_intersections.isEmpty()) {
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
HeightfieldBuffer* newBuffer = new HeightfieldBuffer(info.minimum, info.size,
|
||||
buffer->getHeight(), buffer->getColor(), buffer->getMaterial(), buffer->getMaterials());
|
||||
_fetchVisitor.init(newBuffer);
|
||||
_data->guide(_fetchVisitor);
|
||||
BufferDataPointer pointer(newBuffer);
|
||||
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline(pointer));
|
||||
return STOP_RECURSION;
|
||||
}
|
||||
|
||||
class VoxelAugmentVisitor : public MetavoxelVisitor {
|
||||
public:
|
||||
|
||||
|
@ -2392,27 +1596,13 @@ void DefaultMetavoxelRendererImplementation::augment(MetavoxelData& data, const
|
|||
while (expandedPrevious.getSize() < data.getSize()) {
|
||||
expandedPrevious.expand();
|
||||
}
|
||||
const AttributePointer& heightfieldBufferAttribute =
|
||||
Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute();
|
||||
MetavoxelNode* root = expandedPrevious.getRoot(heightfieldBufferAttribute);
|
||||
if (root) {
|
||||
data.setRoot(heightfieldBufferAttribute, root);
|
||||
root->incrementReferenceCount();
|
||||
}
|
||||
const AttributePointer& voxelBufferAttribute =
|
||||
Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute();
|
||||
root = expandedPrevious.getRoot(voxelBufferAttribute);
|
||||
MetavoxelNode* root = expandedPrevious.getRoot(voxelBufferAttribute);
|
||||
if (root) {
|
||||
data.setRoot(voxelBufferAttribute, root);
|
||||
root->incrementReferenceCount();
|
||||
}
|
||||
HeightfieldRegionVisitor heightfieldRegionVisitor(lod);
|
||||
data.guideToDifferent(expandedPrevious, heightfieldRegionVisitor);
|
||||
|
||||
HeightfieldUpdateVisitor heightfieldUpdateVisitor(lod, heightfieldRegionVisitor.regions,
|
||||
heightfieldRegionVisitor.regionBounds);
|
||||
data.guide(heightfieldUpdateVisitor);
|
||||
|
||||
VoxelAugmentVisitor voxelAugmentVisitor(lod);
|
||||
data.guideToDifferent(expandedPrevious, voxelAugmentVisitor);
|
||||
}
|
||||
|
@ -2535,19 +1725,6 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
|
|||
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) {
|
||||
_baseHeightfieldProgram.bind();
|
||||
|
||||
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
|
||||
data.guide(heightfieldRenderVisitor);
|
||||
|
||||
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
|
||||
|
||||
_baseHeightfieldProgram.release();
|
||||
}
|
||||
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {
|
||||
glEnableClientState(GL_COLOR_ARRAY);
|
||||
glEnableClientState(GL_NORMAL_ARRAY);
|
||||
|
@ -2756,6 +1933,12 @@ void HeightfieldRenderer::init(Spanner* spanner) {
|
|||
connect(heightfield, &Heightfield::materialChanged, this, &HeightfieldRenderer::applyMaterial);
|
||||
}
|
||||
|
||||
class HeightfieldPoint {
|
||||
public:
|
||||
glm::vec3 vertex;
|
||||
glm::vec2 textureCoord;
|
||||
};
|
||||
|
||||
void HeightfieldRenderer::render(bool cursor) {
|
||||
// create the buffer objects lazily
|
||||
Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
|
||||
|
@ -2765,8 +1948,8 @@ void HeightfieldRenderer::render(bool cursor) {
|
|||
int width = heightfield->getHeight()->getWidth();
|
||||
int height = heightfield->getHeight()->getContents().size() / width;
|
||||
|
||||
int innerWidth = width - 2 * HeightfieldBuffer::HEIGHT_BORDER;
|
||||
int innerHeight = height - 2 * HeightfieldBuffer::HEIGHT_BORDER;
|
||||
int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||
int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||
int vertexCount = width * height;
|
||||
int rows = height - 1;
|
||||
int columns = width - 1;
|
||||
|
|
|
@ -78,8 +78,6 @@ public:
|
|||
|
||||
Q_INVOKABLE void setVoxelMaterial(const SharedObjectPointer& spanner, const SharedObjectPointer& material);
|
||||
|
||||
Q_INVOKABLE void deleteTextures(int heightID, int colorID, int textureID);
|
||||
|
||||
signals:
|
||||
|
||||
void rendering();
|
||||
|
@ -185,92 +183,6 @@ public:
|
|||
|
||||
typedef QExplicitlySharedDataPointer<BufferData> BufferDataPointer;
|
||||
|
||||
/// Contains the information necessary to render a heightfield block.
|
||||
class HeightfieldBuffer : public BufferData {
|
||||
public:
|
||||
|
||||
static const int HEIGHT_BORDER;
|
||||
static const int SHARED_EDGE;
|
||||
static const int HEIGHT_EXTENSION;
|
||||
|
||||
HeightfieldBuffer(const glm::vec3& translation, float scale, const QByteArray& height,
|
||||
const QByteArray& color, const QByteArray& material = QByteArray(),
|
||||
const QVector<SharedObjectPointer>& materials = QVector<SharedObjectPointer>());
|
||||
~HeightfieldBuffer();
|
||||
|
||||
const glm::vec3& getTranslation() const { return _translation; }
|
||||
float getScale() const { return _scale; }
|
||||
|
||||
const Box& getHeightBounds() const { return _heightBounds; }
|
||||
const Box& getColorBounds() const { return _colorBounds; }
|
||||
const Box& getMaterialBounds() const { return _materialBounds; }
|
||||
|
||||
QByteArray& getHeight() { return _height; }
|
||||
const QByteArray& getHeight() const { return _height; }
|
||||
|
||||
QByteArray& getColor() { return _color; }
|
||||
const QByteArray& getColor() const { return _color; }
|
||||
|
||||
QByteArray& getMaterial() { return _material; }
|
||||
const QByteArray& getMaterial() const { return _material; }
|
||||
|
||||
QVector<SharedObjectPointer>& getMaterials() { return _materials; }
|
||||
const QVector<SharedObjectPointer>& getMaterials() const { return _materials; }
|
||||
|
||||
QByteArray getUnextendedHeight() const;
|
||||
QByteArray getUnextendedColor(int x = 0, int y = 0) const;
|
||||
|
||||
int getHeightSize() const { return _heightSize; }
|
||||
float getHeightIncrement() const { return _heightIncrement; }
|
||||
|
||||
int getColorSize() const { return _colorSize; }
|
||||
float getColorIncrement() const { return _colorIncrement; }
|
||||
|
||||
int getMaterialSize() const { return _materialSize; }
|
||||
float getMaterialIncrement() const { return _materialIncrement; }
|
||||
|
||||
virtual void render(bool cursor = false);
|
||||
|
||||
private:
|
||||
|
||||
glm::vec3 _translation;
|
||||
float _scale;
|
||||
Box _heightBounds;
|
||||
Box _colorBounds;
|
||||
Box _materialBounds;
|
||||
QByteArray _height;
|
||||
QByteArray _color;
|
||||
QByteArray _material;
|
||||
QVector<SharedObjectPointer> _materials;
|
||||
GLuint _heightTextureID;
|
||||
GLuint _colorTextureID;
|
||||
GLuint _materialTextureID;
|
||||
QVector<NetworkTexturePointer> _networkTextures;
|
||||
int _heightSize;
|
||||
float _heightIncrement;
|
||||
int _colorSize;
|
||||
float _colorIncrement;
|
||||
int _materialSize;
|
||||
float _materialIncrement;
|
||||
|
||||
typedef QPair<QOpenGLBuffer, QOpenGLBuffer> BufferPair;
|
||||
static QHash<int, BufferPair> _bufferPairs;
|
||||
};
|
||||
|
||||
/// Convenience class for rendering a preview of a heightfield.
|
||||
class HeightfieldPreview {
|
||||
public:
|
||||
|
||||
void setBuffers(const QVector<BufferDataPointer>& buffers) { _buffers = buffers; }
|
||||
const QVector<BufferDataPointer>& getBuffers() const { return _buffers; }
|
||||
|
||||
void render(const glm::vec3& translation, float scale) const;
|
||||
|
||||
private:
|
||||
|
||||
QVector<BufferDataPointer> _buffers;
|
||||
};
|
||||
|
||||
/// Describes contents of a vertex in a voxel buffer.
|
||||
class VoxelPoint {
|
||||
public:
|
||||
|
|
Loading…
Reference in a new issue