mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 23:57:13 +02:00
When we set heightfield layers, break it up into quadtree.
This commit is contained in:
parent
fc16207c08
commit
a987e7ce10
2 changed files with 109 additions and 5 deletions
|
@ -1145,6 +1145,94 @@ HeightfieldNode::HeightfieldNode(const HeightfieldHeightPointer& height, const H
|
||||||
_material(material) {
|
_material(material) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int HEIGHT_LEAF_SIZE = 256 + HeightfieldHeight::HEIGHT_EXTENSION;
|
||||||
|
|
||||||
|
void HeightfieldNode::setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||||
|
const HeightfieldMaterialPointer& material) {
|
||||||
|
clearChildren();
|
||||||
|
|
||||||
|
int heightWidth = height->getWidth();
|
||||||
|
if (heightWidth <= HEIGHT_LEAF_SIZE) {
|
||||||
|
_height = height;
|
||||||
|
_color = color;
|
||||||
|
_material = material;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int heightHeight = height->getContents().size() / heightWidth;
|
||||||
|
int innerChildHeightWidth = (heightWidth - HeightfieldHeight::HEIGHT_EXTENSION) / 2;
|
||||||
|
int innerChildHeightHeight = (heightHeight - HeightfieldHeight::HEIGHT_EXTENSION) / 2;
|
||||||
|
int childHeightWidth = innerChildHeightWidth + HeightfieldHeight::HEIGHT_EXTENSION;
|
||||||
|
int childHeightHeight = innerChildHeightHeight + HeightfieldHeight::HEIGHT_EXTENSION;
|
||||||
|
|
||||||
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
|
QVector<quint16> childHeightContents(childHeightWidth * childHeightHeight);
|
||||||
|
quint16* heightDest = childHeightContents.data();
|
||||||
|
bool maximumX = (i & X_MAXIMUM_FLAG), maximumY = (i & Y_MAXIMUM_FLAG);
|
||||||
|
const quint16* heightSrc = height->getContents().constData() + (maximumY ? innerChildHeightHeight * heightWidth : 0) +
|
||||||
|
(maximumX ? innerChildHeightWidth : 0);
|
||||||
|
for (int z = 0; z < childHeightHeight; z++, heightDest += childHeightWidth, heightSrc += heightWidth) {
|
||||||
|
memcpy(heightDest, heightSrc, childHeightWidth * sizeof(quint16));
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldColorPointer childColor;
|
||||||
|
if (color) {
|
||||||
|
int colorWidth = color->getWidth();
|
||||||
|
int colorHeight = color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES);
|
||||||
|
int innerChildColorWidth = (colorWidth - HeightfieldData::SHARED_EDGE) / 2;
|
||||||
|
int innerChildColorHeight = (colorHeight - HeightfieldData::SHARED_EDGE) / 2;
|
||||||
|
int childColorWidth = innerChildColorWidth + HeightfieldData::SHARED_EDGE;
|
||||||
|
int childColorHeight = innerChildColorHeight + HeightfieldData::SHARED_EDGE;
|
||||||
|
QByteArray childColorContents(childColorWidth * childColorHeight * DataBlock::COLOR_BYTES, 0);
|
||||||
|
char* dest = childColorContents.data();
|
||||||
|
const char* src = color->getContents().constData() + ((maximumY ? innerChildColorHeight * colorWidth : 0) +
|
||||||
|
(maximumX ? innerChildColorWidth : 0)) * DataBlock::COLOR_BYTES;
|
||||||
|
for (int z = 0; z < childColorHeight; z++, dest += childColorWidth * DataBlock::COLOR_BYTES,
|
||||||
|
src += colorWidth * DataBlock::COLOR_BYTES) {
|
||||||
|
memcpy(dest, src, childColorWidth * DataBlock::COLOR_BYTES);
|
||||||
|
}
|
||||||
|
childColor = new HeightfieldColor(childColorWidth, childColorContents);
|
||||||
|
}
|
||||||
|
|
||||||
|
HeightfieldMaterialPointer childMaterial;
|
||||||
|
if (material) {
|
||||||
|
int materialWidth = material->getWidth();
|
||||||
|
int materialHeight = material->getContents().size() / materialWidth;
|
||||||
|
int innerChildMaterialWidth = (materialWidth - HeightfieldData::SHARED_EDGE) / 2;
|
||||||
|
int innerChildMaterialHeight = (materialHeight - HeightfieldData::SHARED_EDGE) / 2;
|
||||||
|
int childMaterialWidth = innerChildMaterialWidth + HeightfieldData::SHARED_EDGE;
|
||||||
|
int childMaterialHeight = innerChildMaterialHeight + HeightfieldData::SHARED_EDGE;
|
||||||
|
QByteArray childMaterialContents(childMaterialWidth * childMaterialHeight, 0);
|
||||||
|
QVector<SharedObjectPointer> childMaterials;
|
||||||
|
uchar* dest = (uchar*)childMaterialContents.data();
|
||||||
|
const uchar* src = (const uchar*)material->getContents().data() +
|
||||||
|
(maximumY ? innerChildMaterialHeight * materialWidth : 0) + (maximumX ? innerChildMaterialWidth : 0);
|
||||||
|
QHash<int, int> materialMap;
|
||||||
|
for (int z = 0; z < childMaterialHeight; z++, dest += childMaterialWidth, src += materialWidth) {
|
||||||
|
const uchar* lineSrc = src;
|
||||||
|
for (uchar* lineDest = dest, *end = dest + childMaterialWidth; lineDest != end; lineDest++, lineSrc++) {
|
||||||
|
int value = *lineSrc;
|
||||||
|
if (value != 0) {
|
||||||
|
int& mapping = materialMap[value];
|
||||||
|
if (mapping == 0) {
|
||||||
|
childMaterials.append(material->getMaterials().at(value - 1));
|
||||||
|
mapping = childMaterials.size();
|
||||||
|
}
|
||||||
|
value = mapping;
|
||||||
|
}
|
||||||
|
*lineDest = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
childMaterial = new HeightfieldMaterial(childMaterialWidth, childMaterialContents, childMaterials);
|
||||||
|
}
|
||||||
|
|
||||||
|
_children[i] = new HeightfieldNode();
|
||||||
|
_children[i]->setContents(HeightfieldHeightPointer(new HeightfieldHeight(childHeightWidth, childHeightContents)),
|
||||||
|
childColor, childMaterial);
|
||||||
|
}
|
||||||
|
|
||||||
|
mergeChildren();
|
||||||
|
}
|
||||||
|
|
||||||
bool HeightfieldNode::isLeaf() const {
|
bool HeightfieldNode::isLeaf() const {
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
if (_children[i]) {
|
if (_children[i]) {
|
||||||
|
@ -1406,8 +1494,7 @@ void HeightfieldNode::mergeChildren() {
|
||||||
|
|
||||||
Heightfield::Heightfield() :
|
Heightfield::Heightfield() :
|
||||||
_aspectY(1.0f),
|
_aspectY(1.0f),
|
||||||
_aspectZ(1.0f),
|
_aspectZ(1.0f) {
|
||||||
_root(new HeightfieldNode()) {
|
|
||||||
|
|
||||||
connect(this, &Heightfield::translationChanged, this, &Heightfield::updateBounds);
|
connect(this, &Heightfield::translationChanged, this, &Heightfield::updateBounds);
|
||||||
connect(this, &Heightfield::rotationChanged, this, &Heightfield::updateBounds);
|
connect(this, &Heightfield::rotationChanged, this, &Heightfield::updateBounds);
|
||||||
|
@ -1415,6 +1502,11 @@ Heightfield::Heightfield() :
|
||||||
connect(this, &Heightfield::aspectYChanged, this, &Heightfield::updateBounds);
|
connect(this, &Heightfield::aspectYChanged, this, &Heightfield::updateBounds);
|
||||||
connect(this, &Heightfield::aspectZChanged, this, &Heightfield::updateBounds);
|
connect(this, &Heightfield::aspectZChanged, this, &Heightfield::updateBounds);
|
||||||
updateBounds();
|
updateBounds();
|
||||||
|
|
||||||
|
connect(this, &Heightfield::heightChanged, this, &Heightfield::updateRoot);
|
||||||
|
connect(this, &Heightfield::colorChanged, this, &Heightfield::updateRoot);
|
||||||
|
connect(this, &Heightfield::materialChanged, this, &Heightfield::updateRoot);
|
||||||
|
updateRoot();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Heightfield::setAspectY(float aspectY) {
|
void Heightfield::setAspectY(float aspectY) {
|
||||||
|
@ -2486,6 +2578,13 @@ void Heightfield::updateBounds() {
|
||||||
setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(glm::vec3(), extent));
|
setBounds(glm::translate(getTranslation()) * rotationMatrix * Box(glm::vec3(), extent));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Heightfield::updateRoot() {
|
||||||
|
_root = new HeightfieldNode();
|
||||||
|
if (_height) {
|
||||||
|
_root->setContents(_height, _color, _material);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const {
|
MetavoxelLOD Heightfield::transformLOD(const MetavoxelLOD& lod) const {
|
||||||
// after transforming into unit space, we scale the threshold in proportion to vertical distance
|
// after transforming into unit space, we scale the threshold in proportion to vertical distance
|
||||||
glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ));
|
glm::vec3 inverseScale(1.0f / getScale(), 1.0f / (getScale() * _aspectY), 1.0f / (getScale() * _aspectZ));
|
||||||
|
|
|
@ -494,6 +494,9 @@ public:
|
||||||
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
||||||
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
||||||
|
|
||||||
|
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||||
|
const HeightfieldMaterialPointer& material);
|
||||||
|
|
||||||
const HeightfieldHeightPointer& getHeight() const { return _height; }
|
const HeightfieldHeightPointer& getHeight() const { return _height; }
|
||||||
const HeightfieldColorPointer& getColor() const { return _color; }
|
const HeightfieldColorPointer& getColor() const { return _color; }
|
||||||
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
||||||
|
@ -533,9 +536,10 @@ class Heightfield : public Transformable {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged)
|
Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged)
|
||||||
Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged)
|
Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged)
|
||||||
Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged)
|
Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged STORED false)
|
||||||
Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged)
|
Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false)
|
||||||
Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged DESIGNABLE false)
|
Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false
|
||||||
|
DESIGNABLE false)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
@ -600,6 +604,7 @@ protected:
|
||||||
private slots:
|
private slots:
|
||||||
|
|
||||||
void updateBounds();
|
void updateBounds();
|
||||||
|
void updateRoot();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue