mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 10:28:22 +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) {
|
||||
}
|
||||
|
||||
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 {
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
if (_children[i]) {
|
||||
|
@ -1406,8 +1494,7 @@ void HeightfieldNode::mergeChildren() {
|
|||
|
||||
Heightfield::Heightfield() :
|
||||
_aspectY(1.0f),
|
||||
_aspectZ(1.0f),
|
||||
_root(new HeightfieldNode()) {
|
||||
_aspectZ(1.0f) {
|
||||
|
||||
connect(this, &Heightfield::translationChanged, 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::aspectZChanged, this, &Heightfield::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) {
|
||||
|
@ -2486,6 +2578,13 @@ void Heightfield::updateBounds() {
|
|||
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 {
|
||||
// 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));
|
||||
|
|
|
@ -494,6 +494,9 @@ public:
|
|||
const HeightfieldColorPointer& color = HeightfieldColorPointer(),
|
||||
const HeightfieldMaterialPointer& material = HeightfieldMaterialPointer());
|
||||
|
||||
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||
const HeightfieldMaterialPointer& material);
|
||||
|
||||
const HeightfieldHeightPointer& getHeight() const { return _height; }
|
||||
const HeightfieldColorPointer& getColor() const { return _color; }
|
||||
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
||||
|
@ -533,9 +536,10 @@ class Heightfield : public Transformable {
|
|||
Q_OBJECT
|
||||
Q_PROPERTY(float aspectY MEMBER _aspectY WRITE setAspectY NOTIFY aspectYChanged)
|
||||
Q_PROPERTY(float aspectZ MEMBER _aspectZ WRITE setAspectZ NOTIFY aspectZChanged)
|
||||
Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged)
|
||||
Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged)
|
||||
Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged DESIGNABLE false)
|
||||
Q_PROPERTY(HeightfieldHeightPointer height MEMBER _height WRITE setHeight NOTIFY heightChanged STORED false)
|
||||
Q_PROPERTY(HeightfieldColorPointer color MEMBER _color WRITE setColor NOTIFY colorChanged STORED false)
|
||||
Q_PROPERTY(HeightfieldMaterialPointer material MEMBER _material WRITE setMaterial NOTIFY materialChanged STORED false
|
||||
DESIGNABLE false)
|
||||
|
||||
public:
|
||||
|
||||
|
@ -600,6 +604,7 @@ protected:
|
|||
private slots:
|
||||
|
||||
void updateBounds();
|
||||
void updateRoot();
|
||||
|
||||
private:
|
||||
|
||||
|
|
Loading…
Reference in a new issue