mirror of
https://github.com/overte-org/overte.git
synced 2025-08-09 02:56: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);
|
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 {
|
class SpannerRenderVisitor : public SpannerVisitor {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -2090,48 +2096,10 @@ void StaticModelRenderer::applyURL(const QUrl& url) {
|
||||||
HeightfieldRenderer::HeightfieldRenderer() {
|
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 X_MAXIMUM_FLAG = 1;
|
||||||
const int Y_MAXIMUM_FLAG = 2;
|
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::vec2& minimum, float size, bool contained, bool cursor) {
|
||||||
const glm::quat& rotation = heightfield->getRotation();
|
const glm::quat& rotation = heightfield->getRotation();
|
||||||
glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(),
|
glm::vec3 scale(heightfield->getScale() * size, heightfield->getScale() * heightfield->getAspectY(),
|
||||||
|
@ -2148,19 +2116,44 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
||||||
contained = true;
|
contained = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isLeaf() && lod.shouldSubdivide(minimum, size)) {
|
if (!node->isLeaf() && lod.shouldSubdivide(minimum, size)) {
|
||||||
float nextSize = size * 0.5f;
|
float nextSize = size * 0.5f;
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
for (int i = 0; i < HeightfieldNode::CHILD_COUNT; i++) {
|
||||||
_children[i]->render(heightfield, lod, minimum + glm::vec2(i & X_MAXIMUM_FLAG ? nextSize : 0.0f,
|
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);
|
i & Y_MAXIMUM_FLAG ? nextSize : 0.0f), nextSize, contained, cursor);
|
||||||
}
|
}
|
||||||
return;
|
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;
|
return;
|
||||||
}
|
}
|
||||||
int width = _heightfieldNode->getHeight()->getWidth();
|
int width = node->getHeight()->getWidth();
|
||||||
int height = _heightfieldNode->getHeight()->getContents().size() / width;
|
int height = node->getHeight()->getContents().size() / width;
|
||||||
int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
int innerWidth = width - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||||
int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
int innerHeight = height - 2 * HeightfieldHeight::HEIGHT_BORDER;
|
||||||
int vertexCount = width * height;
|
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_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
|
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,
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R16, width, height, 0,
|
||||||
GL_RED, GL_UNSIGNED_SHORT, heightContents.constData());
|
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_MIN_FILTER, GL_LINEAR);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
if (_heightfieldNode->getColor()) {
|
if (node->getColor()) {
|
||||||
const QByteArray& contents = _heightfieldNode->getColor()->getContents();
|
const QByteArray& contents = node->getColor()->getContents();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, _heightfieldNode->getColor()->getWidth(),
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, node->getColor()->getWidth(),
|
||||||
contents.size() / (_heightfieldNode->getColor()->getWidth() * DataBlock::COLOR_BYTES),
|
contents.size() / (node->getColor()->getWidth() * DataBlock::COLOR_BYTES),
|
||||||
0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData());
|
0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData());
|
||||||
|
|
||||||
} else {
|
} 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_MAG_FILTER, GL_NEAREST);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||||
if (_heightfieldNode->getMaterial()) {
|
if (node->getMaterial()) {
|
||||||
const QByteArray& contents = _heightfieldNode->getMaterial()->getContents();
|
const QByteArray& contents = node->getMaterial()->getContents();
|
||||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, _heightfieldNode->getMaterial()->getWidth(),
|
glTexImage2D(GL_TEXTURE_2D, 0, GL_R8, node->getMaterial()->getWidth(),
|
||||||
contents.size() / _heightfieldNode->getMaterial()->getWidth(),
|
contents.size() / node->getMaterial()->getWidth(),
|
||||||
0, GL_RED, GL_UNSIGNED_BYTE, contents.constData());
|
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());
|
_networkTextures.resize(materials.size());
|
||||||
for (int i = 0; i < materials.size(); i++) {
|
for (int i = 0; i < materials.size(); i++) {
|
||||||
const SharedObjectPointer& material = materials.at(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(1.0f, 0.0f, 0.0f)) / scale.x,
|
||||||
glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z);
|
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 i = 0; i < materials.size(); i += SPLAT_COUNT) {
|
||||||
for (int j = 0; j < SPLAT_COUNT; j++) {
|
for (int j = 0; j < SPLAT_COUNT; j++) {
|
||||||
int index = i + j;
|
int index = i + j;
|
||||||
|
@ -2355,14 +2348,5 @@ void HeightfieldRendererNode::render(Heightfield* heightfield, const MetavoxelLO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool HeightfieldRendererNode::isLeaf() const {
|
QHash<HeightfieldNodeRenderer::IntPair, HeightfieldNodeRenderer::BufferPair> HeightfieldNodeRenderer::_bufferPairs;
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
|
||||||
if (_children[i]) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
QHash<HeightfieldRendererNode::IntPair, HeightfieldRendererNode::BufferPair> HeightfieldRendererNode::_bufferPairs;
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,6 @@
|
||||||
#include "renderer/ProgramObject.h"
|
#include "renderer/ProgramObject.h"
|
||||||
|
|
||||||
class HeightfieldBaseLayerBatch;
|
class HeightfieldBaseLayerBatch;
|
||||||
class HeightfieldRendererNode;
|
|
||||||
class HeightfieldSplatBatch;
|
class HeightfieldSplatBatch;
|
||||||
class HermiteBatch;
|
class HermiteBatch;
|
||||||
class Model;
|
class Model;
|
||||||
|
@ -91,7 +90,9 @@ public:
|
||||||
void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); }
|
void addVoxelSplatBatch(const VoxelSplatBatch& batch) { _voxelSplatBatches.append(batch); }
|
||||||
|
|
||||||
void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); }
|
void addHermiteBatch(const HermiteBatch& batch) { _hermiteBatches.append(batch); }
|
||||||
|
|
||||||
|
Q_INVOKABLE void deleteTextures(int heightTextureID, int colorTextureID, int materialTextureID) const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
|
||||||
void rendering();
|
void rendering();
|
||||||
|
@ -431,8 +432,6 @@ private:
|
||||||
Model* _model;
|
Model* _model;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef QExplicitlySharedDataPointer<HeightfieldRendererNode> HeightfieldRendererNodePointer;
|
|
||||||
|
|
||||||
/// Renders heightfields.
|
/// Renders heightfields.
|
||||||
class HeightfieldRenderer : public SpannerRenderer {
|
class HeightfieldRenderer : public SpannerRenderer {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
@ -441,38 +440,21 @@ public:
|
||||||
|
|
||||||
Q_INVOKABLE HeightfieldRenderer();
|
Q_INVOKABLE HeightfieldRenderer();
|
||||||
|
|
||||||
virtual void init(Spanner* spanner);
|
|
||||||
virtual void render(const MetavoxelLOD& lod = MetavoxelLOD(), bool contained = false, bool cursor = false);
|
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.
|
/// Renders a single quadtree node.
|
||||||
class HeightfieldRendererNode : public QSharedData {
|
class HeightfieldNodeRenderer : public AbstractHeightfieldNodeRenderer {
|
||||||
public:
|
public:
|
||||||
|
|
||||||
static const int CHILD_COUNT = 4;
|
HeightfieldNodeRenderer();
|
||||||
|
virtual ~HeightfieldNodeRenderer();
|
||||||
|
|
||||||
HeightfieldRendererNode(const HeightfieldNodePointer& heightfieldNode);
|
void render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||||
virtual ~HeightfieldRendererNode();
|
const glm::quat& rotation, const glm::vec3& scale, bool cursor);
|
||||||
|
|
||||||
void render(Heightfield* heightfield, const MetavoxelLOD& lod, const glm::vec2& minimum, float size,
|
|
||||||
bool contained, bool cursor = false);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
bool isLeaf() const;
|
|
||||||
|
|
||||||
HeightfieldNodePointer _heightfieldNode;
|
|
||||||
|
|
||||||
HeightfieldRendererNodePointer _children[CHILD_COUNT];
|
|
||||||
|
|
||||||
GLuint _heightTextureID;
|
GLuint _heightTextureID;
|
||||||
GLuint _colorTextureID;
|
GLuint _colorTextureID;
|
||||||
GLuint _materialTextureID;
|
GLuint _materialTextureID;
|
||||||
|
|
|
@ -1143,7 +1143,23 @@ HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const H
|
||||||
const HeightfieldMaterialPointer& material) :
|
const HeightfieldMaterialPointer& material) :
|
||||||
_height(height),
|
_height(height),
|
||||||
_color(color),
|
_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;
|
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)];
|
return src[(int)glm::round(relative.z) * width + (int)glm::round(relative.x)];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AbstractHeightfieldNodeRenderer::~AbstractHeightfieldNodeRenderer() {
|
||||||
|
}
|
||||||
|
|
||||||
Heightfield::Heightfield() :
|
Heightfield::Heightfield() :
|
||||||
_aspectY(1.0f),
|
_aspectY(1.0f),
|
||||||
_aspectZ(1.0f) {
|
_aspectZ(1.0f) {
|
||||||
|
|
|
@ -17,6 +17,8 @@
|
||||||
#include "AttributeRegistry.h"
|
#include "AttributeRegistry.h"
|
||||||
#include "MetavoxelUtil.h"
|
#include "MetavoxelUtil.h"
|
||||||
|
|
||||||
|
class AbstractHeightfieldNodeRenderer;
|
||||||
|
class Heightfield;
|
||||||
class HeightfieldColor;
|
class HeightfieldColor;
|
||||||
class HeightfieldHeight;
|
class HeightfieldHeight;
|
||||||
class HeightfieldMaterial;
|
class HeightfieldMaterial;
|
||||||
|
@ -499,6 +501,10 @@ public:
|
||||||
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
||||||
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
||||||
|
|
||||||
|
HeightfieldNode(const HeightfieldNode& other);
|
||||||
|
|
||||||
|
~HeightfieldNode();
|
||||||
|
|
||||||
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||||
const HeightfieldMaterialPointer& material);
|
const HeightfieldMaterialPointer& material);
|
||||||
|
|
||||||
|
@ -511,6 +517,9 @@ public:
|
||||||
void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; }
|
void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; }
|
||||||
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
||||||
|
|
||||||
|
void setRenderer(AbstractHeightfieldNodeRenderer* renderer) { _renderer = renderer; }
|
||||||
|
AbstractHeightfieldNodeRenderer* getRenderer() const { return _renderer; }
|
||||||
|
|
||||||
bool isLeaf() const;
|
bool isLeaf() const;
|
||||||
|
|
||||||
void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; }
|
void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; }
|
||||||
|
@ -559,6 +568,15 @@ private:
|
||||||
HeightfieldMaterialPointer _material;
|
HeightfieldMaterialPointer _material;
|
||||||
|
|
||||||
HeightfieldNodePointer _children[CHILD_COUNT];
|
HeightfieldNodePointer _children[CHILD_COUNT];
|
||||||
|
|
||||||
|
AbstractHeightfieldNodeRenderer* _renderer;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// Base class for heightfield node rendering.
|
||||||
|
class AbstractHeightfieldNodeRenderer {
|
||||||
|
public:
|
||||||
|
|
||||||
|
virtual ~AbstractHeightfieldNodeRenderer();
|
||||||
};
|
};
|
||||||
|
|
||||||
/// A heightfield represented as a spanner.
|
/// A heightfield represented as a spanner.
|
||||||
|
|
Loading…
Reference in a new issue