mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Only recreate the renderers for nodes that have changed.
This commit is contained in:
parent
7a81e6c9e1
commit
8fb766a5d0
4 changed files with 97 additions and 94 deletions
|
@ -578,6 +578,12 @@ void MetavoxelSystem::setVoxelMaterial(const SharedObjectPointer& spanner, const
|
|||
applyMaterialEdit(edit, true);
|
||||
}
|
||||
|
||||
void MetavoxelSystem::deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const {
|
||||
glDeleteTextures(1, (const GLuint*)&heightTextureID);
|
||||
glDeleteTextures(1, (const GLuint*)&colorTextureID);
|
||||
glDeleteTextures(1, (const GLuint*)&materialTextureID);
|
||||
}
|
||||
|
||||
class SpannerRenderVisitor : public SpannerVisitor {
|
||||
public:
|
||||
|
||||
|
@ -2090,48 +2096,10 @@ void StaticModelRenderer::applyURL(const QUrl& url) {
|
|||
HeightfieldRenderer::HeightfieldRenderer() {
|
||||
}
|
||||
|
||||
void HeightfieldRenderer::init(Spanner* spanner) {
|
||||
SpannerRenderer::init(spanner);
|
||||
|
||||
Heightfield* heightfield = static_cast<Heightfield*>(spanner);
|
||||
connect(heightfield, &Heightfield::rootChanged, this, &HeightfieldRenderer::updateRoot);
|
||||
updateRoot();
|
||||
}
|
||||
|
||||
void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) {
|
||||
Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
|
||||
_root->render(heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor);
|
||||
}
|
||||
|
||||
void HeightfieldRenderer::updateRoot() {
|
||||
Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
|
||||
_root = new HeightfieldRendererNode(heightfield->getRoot());
|
||||
}
|
||||
|
||||
HeightfieldRendererNode::HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode) :
|
||||
_heightfieldNode(heightfieldNode),
|
||||
_heightTextureID(0),
|
||||
_colorTextureID(0),
|
||||
_materialTextureID(0) {
|
||||
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
HeightfieldNodePointer child = heightfieldNode->getChild(i);
|
||||
if (child) {
|
||||
_children[i] = new HeightfieldRendererNode(child);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
HeightfieldRendererNode::~HeightfieldRendererNode() {
|
||||
glDeleteTextures(1, &_heightTextureID);
|
||||
glDeleteTextures(1, &_colorTextureID);
|
||||
glDeleteTextures(1, &_materialTextureID);
|
||||
}
|
||||
|
||||
const int X_MAXIMUM_FLAG = 1;
|
||||
const int Y_MAXIMUM_FLAG = 2;
|
||||
|
||||
void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLOD& lod,
|
||||
static void renderNode(const HeightfieldNodePointer& node, Heightfield* heightfield, const MetavoxelLOD& lod,
|
||||
const glm::vec2& minimum, float size, bool contained, bool cursor) {
|
||||
const glm::quat& rotation = heightfield->getRotation();
|
||||
glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(),
|
||||
|
@ -2148,19 +2116,44 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
contained = true;
|
||||
}
|
||||
}
|
||||
if (!isLeaf() && lod.shouldSubdivide(minimum, size)) {
|
||||
if (!node->isLeaf() && lod.shouldSubdivide(minimum, size)) {
|
||||
float nextSize = size * 0.5f;
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i]->render(heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f,
|
||||
for (int i = 0; i < HeightfieldNode::CHILD_COUNT; i++) {
|
||||
renderNode(node->getChild(i), heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f,
|
||||
i & Y_MAXIMUM_FLAG ? nextSize : 0.0f), nextSize, contained, cursor);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!_heightfieldNode->getHeight()) {
|
||||
HeightfieldNodeRenderer* renderer = static_cast<HeightfieldNodeRenderer*>(node->getRenderer());
|
||||
if (!renderer) {
|
||||
node->setRenderer(renderer = new HeightfieldNodeRenderer());
|
||||
}
|
||||
renderer->render(node, translation, rotation, scale, cursor);
|
||||
}
|
||||
|
||||
void HeightfieldRenderer::render(const MetavoxelLOD& lod, bool contained, bool cursor) {
|
||||
Heightfield* heightfield = static_cast<Heightfield*>(_spanner);
|
||||
renderNode(heightfield->getRoot(), heightfield, heightfield->transformLOD(lod), glm::vec2(), 1.0f, contained, cursor);
|
||||
}
|
||||
|
||||
HeightfieldNodeRenderer::HeightfieldNodeRenderer() :
|
||||
_heightTextureID(0),
|
||||
_colorTextureID(0),
|
||||
_materialTextureID(0) {
|
||||
}
|
||||
|
||||
HeightfieldNodeRenderer::~HeightfieldNodeRenderer() {
|
||||
QMetaObject::invokeMethod(Application::getInstance()->getMetavoxels(), "deleteTextures", Q_ARG(int, _heightTextureID),
|
||||
Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID));
|
||||
}
|
||||
|
||||
void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||
const glm::quat& rotation, const glm::vec3& scale, bool cursor) {
|
||||
if (!node->getHeight()) {
|
||||
return;
|
||||
}
|
||||
int width = _heightfieldNode->getHeight()->getWidth();
|
||||
int height = _heightfieldNode->getHeight()->getContents().size() / width;
|
||||
int width = node->getHeight()->getWidth();
|
||||
int height = node->getHeight()->getContents().size() / width;
|
||||
int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||
int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||
int vertexCount = width * height;
|
||||
|
@ -2225,7 +2218,7 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
||||
const QVector<quint16>& heightContents = _heightfieldNode->getHeight()->getContents();
|
||||
const QVector<quint16>& heightContents = node->getHeight()->getContents();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0,
|
||||
GL_RED, GL_UNSIGNED_SHORT, heightContents.constData());
|
||||
|
||||
|
@ -2234,10 +2227,10 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
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 (_heightfieldNode->getColor()) {
|
||||
const QByteArray& contents = _heightfieldNode->getColor()->getContents();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _heightfieldNode->getColor()->getWidth(),
|
||||
contents.size() / (_heightfieldNode->getColor()->getWidth() * DataBlock::COLOR_BYTES),
|
||||
if (node->getColor()) {
|
||||
const QByteArray& contents = node->getColor()->getContents();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, node->getColor()->getWidth(),
|
||||
contents.size() / (node->getColor()->getWidth() * DataBlock::COLOR_BYTES),
|
||||
0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData());
|
||||
|
||||
} else {
|
||||
|
@ -2251,13 +2244,13 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
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);
|
||||
if (_heightfieldNode->getMaterial()) {
|
||||
const QByteArray& contents = _heightfieldNode->getMaterial()->getContents();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, _heightfieldNode->getMaterial()->getWidth(),
|
||||
contents.size() / _heightfieldNode->getMaterial()->getWidth(),
|
||||
if (node->getMaterial()) {
|
||||
const QByteArray& contents = node->getMaterial()->getContents();
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, node->getMaterial()->getWidth(),
|
||||
contents.size() / node->getMaterial()->getWidth(),
|
||||
0, GL_RED, GL_UNSIGNED_BYTE, contents.constData());
|
||||
|
||||
const QVector<SharedObjectPointer>& materials = _heightfieldNode->getMaterial()->getMaterials();
|
||||
const QVector<SharedObjectPointer>& materials = node->getMaterial()->getMaterials();
|
||||
_networkTextures.resize(materials.size());
|
||||
for (int i = 0; i < materials.size(); i++) {
|
||||
const SharedObjectPointer& material = materials.at(i);
|
||||
|
@ -2330,7 +2323,7 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x,
|
||||
glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z);
|
||||
|
||||
const QVector<SharedObjectPointer>& materials = _heightfieldNode->getMaterial()->getMaterials();
|
||||
const QVector<SharedObjectPointer>& materials = node->getMaterial()->getMaterials();
|
||||
for (int i = 0; i < materials.size(); i += SPLAT_COUNT) {
|
||||
for (int j = 0; j < SPLAT_COUNT; j++) {
|
||||
int index = i + j;
|
||||
|
@ -2355,14 +2348,5 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
|||
}
|
||||
}
|
||||
|
||||
bool HeightfieldRendererNode::isLeaf() const {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
if (_children[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
QHash<HeightfieldRendererNode::IntPair, HeightfieldRendererNode::BufferPair> HeightfieldRendererNode::_bufferPairs;
|
||||
QHash<HeightfieldNodeRenderer::IntPair, HeightfieldNodeRenderer::BufferPair> HeightfieldNodeRenderer::_bufferPairs;
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@
|
|||
#include "renderer/ProgramObject.h"
|
||||
|
||||
class HeightfieldBaseLayerBatch;
|
||||
class HeightfieldRendererNode;
|
||||
class HeightfieldSplatBatch;
|
||||
class HermiteBatch;
|
||||
class Model;
|
||||
|
@ -91,7 +90,9 @@ public:
|
|||
void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); }
|
||||
|
||||
void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); }
|
||||
|
||||
|
||||
Q_INVOKABLE void deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const;
|
||||
|
||||
signals:
|
||||
|
||||
void rendering();
|
||||
|
@ -431,8 +432,6 @@ private:
|
|||
Model* _model;
|
||||
};
|
||||
|
||||
typedef QExplicitlySharedDataPointer<HeightfieldRendererNode> HeightfieldRendererNodePointer;
|
||||
|
||||
/// Renders heightfields.
|
||||
class HeightfieldRenderer : public SpannerRenderer {
|
||||
Q_OBJECT
|
||||
|
@ -441,38 +440,21 @@ public:
|
|||
|
||||
Q_INVOKABLE HeightfieldRenderer();
|
||||
|
||||
virtual void init(Spanner* spanner);
|
||||
virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);
|
||||
|
||||
private slots:
|
||||
|
||||
void updateRoot();
|
||||
|
||||
private:
|
||||
|
||||
HeightfieldRendererNodePointer _root;
|
||||
};
|
||||
|
||||
/// A node in the heightfield renderer quadtree.
|
||||
class HeightfieldRendererNode : public QSharedData {
|
||||
/// Renders a single quadtree node.
|
||||
class HeightfieldNodeRenderer : public AbstractHeightfieldNodeRenderer {
|
||||
public:
|
||||
|
||||
static const int CHILD_COUNT = 4;
|
||||
HeightfieldNodeRenderer();
|
||||
virtual ~HeightfieldNodeRenderer();
|
||||
|
||||
HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode);
|
||||
virtual ~HeightfieldRendererNode();
|
||||
|
||||
void render(Heightfield* heightfield, const MetavoxelLOD& lod, const glm::vec2& minimum, float size,
|
||||
bool contained, bool cursor = false);
|
||||
void render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||
const glm::quat& rotation, const glm::vec3& scale, bool cursor);
|
||||
|
||||
private:
|
||||
|
||||
bool isLeaf() const;
|
||||
|
||||
HeightfieldNodePointer _heightfieldNode;
|
||||
|
||||
HeightfieldRendererNodePointer _children[CHILD_COUNT];
|
||||
|
||||
GLuint _heightTextureID;
|
||||
GLuint _colorTextureID;
|
||||
GLuint _materialTextureID;
|
||||
|
|
|
@ -1143,7 +1143,23 @@ HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const H
|
|||
const HeightfieldMaterialPointer& material) :
|
||||
_height(height),
|
||||
_color(color),
|
||||
_material(material) {
|
||||
_material(material),
|
||||
_renderer(NULL) {
|
||||
}
|
||||
|
||||
HeightfieldNode::HeightfieldNode(const HeightfieldNode& other) :
|
||||
_height(other.getHeight()),
|
||||
_color(other.getColor()),
|
||||
_material(other.getMaterial()),
|
||||
_renderer(NULL) {
|
||||
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
_children[i] = other.getChild(i);
|
||||
}
|
||||
}
|
||||
|
||||
HeightfieldNode::~HeightfieldNode() {
|
||||
delete _renderer;
|
||||
}
|
||||
|
||||
const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION;
|
||||
|
@ -2479,6 +2495,9 @@ int HeightfieldNode::getMaterialAt(const glm::vec3& location) const {
|
|||
return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)];
|
||||
}
|
||||
|
||||
AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() {
|
||||
}
|
||||
|
||||
Heightfield::Heightfield() :
|
||||
_aspectY(1.0f),
|
||||
_aspectZ(1.0f) {
|
||||
|
|
|
@ -17,6 +17,8 @@
|
|||
#include "AttributeRegistry.h"
|
||||
#include "MetavoxelUtil.h"
|
||||
|
||||
class AbstractHeightfieldNodeRenderer;
|
||||
class Heightfield;
|
||||
class HeightfieldColor;
|
||||
class HeightfieldHeight;
|
||||
class HeightfieldMaterial;
|
||||
|
@ -499,6 +501,10 @@ public:
|
|||
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
||||
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
||||
|
||||
HeightfieldNode(const HeightfieldNode& other);
|
||||
|
||||
~HeightfieldNode();
|
||||
|
||||
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||
const HeightfieldMaterialPointer& material);
|
||||
|
||||
|
@ -511,6 +517,9 @@ public:
|
|||
void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; }
|
||||
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
||||
|
||||
void setRenderer(AbstractHeightfieldNodeRenderer* renderer) { _renderer = renderer; }
|
||||
AbstractHeightfieldNodeRenderer* getRenderer() const { return _renderer; }
|
||||
|
||||
bool isLeaf() const;
|
||||
|
||||
void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; }
|
||||
|
@ -559,6 +568,15 @@ private:
|
|||
HeightfieldMaterialPointer _material;
|
||||
|
||||
HeightfieldNodePointer _children[CHILD_COUNT];
|
||||
|
||||
AbstractHeightfieldNodeRenderer* _renderer;
|
||||
};
|
||||
|
||||
/// Base class for heightfield node rendering.
|
||||
class AbstractHeightfieldNodeRenderer {
|
||||
public:
|
||||
|
||||
virtual ~AbstractHeightfieldNodeRenderer();
|
||||
};
|
||||
|
||||
/// A heightfield represented as a spanner.
|
||||
|
|
Loading…
Reference in a new issue