mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 17:35:45 +02:00
More work on spanner heightfield edits.
This commit is contained in:
parent
5b4869f43d
commit
46f1fc7c0f
2 changed files with 147 additions and 102 deletions
|
@ -1471,6 +1471,132 @@ bool HeightfieldNode::findRayIntersection(const glm::vec3& origin, const glm::ve
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HeightfieldNode* HeightfieldNode::paintMaterial(const glm::vec3& position, const glm::vec3& radius,
|
||||||
|
const SharedObjectPointer& material, const QColor& color) {
|
||||||
|
if (!isLeaf()) {
|
||||||
|
HeightfieldNode* newNode = this;
|
||||||
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
|
HeightfieldNode* newChild = _children[i]->paintMaterial(position * glm::vec3(2.0f, 1.0f, 2.0f) -
|
||||||
|
glm::vec3(i & X_MAXIMUM_FLAG ? 1.0f : 0.0f, 0.0f, i & Y_MAXIMUM_FLAG ? 1.0f : 0.0f),
|
||||||
|
radius * glm::vec3(2.0f, 1.0f, 2.0f), material, color);
|
||||||
|
if (_children[i] != newChild) {
|
||||||
|
if (newNode == this) {
|
||||||
|
newNode = new HeightfieldNode(*this);
|
||||||
|
}
|
||||||
|
newNode->setChild(i, HeightfieldNodePointer(newChild));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (newNode != this) {
|
||||||
|
newNode->mergeChildren(false, true);
|
||||||
|
}
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
if (!_height || position.x + radius.x < 0.0f || position.z + radius.z < 0.0f ||
|
||||||
|
position.x - radius.x > 1.0f || position.z - radius.z > 1.0f) {
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
int heightWidth = _height->getWidth();
|
||||||
|
int heightHeight = _height->getContents().size() / heightWidth;
|
||||||
|
int baseWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE;
|
||||||
|
int baseHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE;
|
||||||
|
HeightfieldNode* newNode = new HeightfieldNode(*this);
|
||||||
|
|
||||||
|
int colorWidth = baseWidth, colorHeight = baseHeight;
|
||||||
|
QByteArray colorContents;
|
||||||
|
if (_color) {
|
||||||
|
colorWidth = _color->getWidth();
|
||||||
|
colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES);
|
||||||
|
colorContents = _color->getContents();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
colorContents = QByteArray(baseWidth * baseHeight * DataBlock::COLOR_BYTES, 0xFF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int materialWidth = baseWidth, materialHeight = baseHeight;
|
||||||
|
QByteArray materialContents;
|
||||||
|
QVector<SharedObjectPointer> materials;
|
||||||
|
if (_material) {
|
||||||
|
materialWidth = _material->getWidth();
|
||||||
|
materialHeight = _material->getContents().size() / materialWidth;
|
||||||
|
materialContents = _material->getContents();
|
||||||
|
materials = _material->getMaterials();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
materialContents = QByteArray(baseWidth * baseHeight, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
int highestX = colorWidth - 1;
|
||||||
|
int highestZ = colorHeight - 1;
|
||||||
|
glm::vec3 scale((float)highestX, 1.0f, (float)highestZ);
|
||||||
|
glm::vec3 center = position * scale;
|
||||||
|
|
||||||
|
glm::vec3 extents = radius * scale;
|
||||||
|
glm::vec3 start = glm::floor(center - extents);
|
||||||
|
glm::vec3 end = glm::ceil(center + extents);
|
||||||
|
|
||||||
|
// paint all points within the radius
|
||||||
|
float z = qMax(start.z, 0.0f);
|
||||||
|
float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX);
|
||||||
|
int stride = colorWidth * DataBlock::COLOR_BYTES;
|
||||||
|
uchar* lineDest = (uchar*)colorContents.data() + (int)z * stride + (int)startX * DataBlock::COLOR_BYTES;
|
||||||
|
float squaredRadius = extents.x * extents.x;
|
||||||
|
float multiplierZ = extents.x / extents.z;
|
||||||
|
char red = color.red(), green = color.green(), blue = color.blue();
|
||||||
|
bool changed = false;
|
||||||
|
for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) {
|
||||||
|
uchar* dest = lineDest;
|
||||||
|
for (float x = startX; x <= endX; x += 1.0f, dest += DataBlock::COLOR_BYTES) {
|
||||||
|
float dx = x - center.x, dz = (z - center.z) * multiplierZ;
|
||||||
|
if (dx * dx + dz * dz <= squaredRadius) {
|
||||||
|
dest[0] = red;
|
||||||
|
dest[1] = green;
|
||||||
|
dest[2] = blue;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineDest += stride;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
newNode->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, colorContents)));
|
||||||
|
}
|
||||||
|
|
||||||
|
highestX = materialWidth - 1;
|
||||||
|
highestZ = materialHeight - 1;
|
||||||
|
scale = glm::vec3((float)highestX, 1.0f, (float)highestZ);
|
||||||
|
center = position * scale;
|
||||||
|
|
||||||
|
extents = radius * scale;
|
||||||
|
start = glm::floor(center - extents);
|
||||||
|
end = glm::ceil(center + extents);
|
||||||
|
|
||||||
|
// paint all points within the radius
|
||||||
|
z = qMax(start.z, 0.0f);
|
||||||
|
startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX);
|
||||||
|
lineDest = (uchar*)materialContents.data() + (int)z * materialWidth + (int)startX;
|
||||||
|
squaredRadius = extents.x * extents.x;
|
||||||
|
multiplierZ = extents.x / extents.z;
|
||||||
|
uchar materialIndex = getMaterialIndex(material, materials, materialContents);
|
||||||
|
changed = false;
|
||||||
|
for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) {
|
||||||
|
uchar* dest = lineDest;
|
||||||
|
for (float x = startX; x <= endX; x += 1.0f, dest++) {
|
||||||
|
float dx = x - center.x, dz = (z - center.z) * multiplierZ;
|
||||||
|
if (dx * dx + dz * dz <= squaredRadius) {
|
||||||
|
*dest = materialIndex;
|
||||||
|
changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lineDest += materialWidth;
|
||||||
|
}
|
||||||
|
if (changed) {
|
||||||
|
clearUnusedMaterials(materials, materialContents);
|
||||||
|
newNode->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth,
|
||||||
|
materialContents, materials)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return newNode;
|
||||||
|
}
|
||||||
|
|
||||||
void HeightfieldNode::read(HeightfieldStreamState& state) {
|
void HeightfieldNode::read(HeightfieldStreamState& state) {
|
||||||
clearChildren();
|
clearChildren();
|
||||||
|
|
||||||
|
@ -1718,7 +1844,7 @@ void HeightfieldNode::clearChildren() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeightfieldNode::mergeChildren() {
|
void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) {
|
||||||
if (isLeaf()) {
|
if (isLeaf()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1751,7 +1877,7 @@ void HeightfieldNode::mergeChildren() {
|
||||||
materialHeight = qMax(materialHeight, childMaterialHeight);
|
materialHeight = qMax(materialHeight, childMaterialHeight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (heightWidth > 0) {
|
if (heightWidth > 0 && height) {
|
||||||
QVector<quint16> heightContents(heightWidth * heightHeight);
|
QVector<quint16> heightContents(heightWidth * heightHeight);
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
HeightfieldHeightPointer childHeight = _children[i]->getHeight();
|
HeightfieldHeightPointer childHeight = _children[i]->getHeight();
|
||||||
|
@ -1780,9 +1906,12 @@ void HeightfieldNode::mergeChildren() {
|
||||||
}
|
}
|
||||||
_height = new HeightfieldHeight(heightWidth, heightContents);
|
_height = new HeightfieldHeight(heightWidth, heightContents);
|
||||||
|
|
||||||
} else {
|
} else if (height) {
|
||||||
_height.reset();
|
_height.reset();
|
||||||
}
|
}
|
||||||
|
if (!colorMaterial) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (colorWidth > 0) {
|
if (colorWidth > 0) {
|
||||||
QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0);
|
QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0);
|
||||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||||
|
@ -1947,107 +2076,14 @@ bool Heightfield::findRayIntersection(const glm::vec3& origin, const glm::vec3&
|
||||||
|
|
||||||
Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius,
|
Spanner* Heightfield::paintMaterial(const glm::vec3& position, float radius,
|
||||||
const SharedObjectPointer& material, const QColor& color) {
|
const SharedObjectPointer& material, const QColor& color) {
|
||||||
if (!_height) {
|
glm::vec3 inverseScale(1.0f / getScale(), 1.0f, 1.0f / getScale() * _aspectZ);
|
||||||
|
HeightfieldNode* newRoot = _root->paintMaterial(glm::inverse(getRotation()) * (position - getTranslation()) *
|
||||||
|
inverseScale, radius * inverseScale, material, color);
|
||||||
|
if (_root == newRoot) {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
int heightWidth = _height->getWidth();
|
|
||||||
int heightHeight = _height->getContents().size() / heightWidth;
|
|
||||||
int baseWidth = heightWidth - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE;
|
|
||||||
int baseHeight = heightHeight - HeightfieldHeight::HEIGHT_EXTENSION + HeightfieldData::SHARED_EDGE;
|
|
||||||
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
|
Heightfield* newHeightfield = static_cast<Heightfield*>(clone(true));
|
||||||
|
newHeightfield->setRoot(HeightfieldNodePointer(newRoot));
|
||||||
int colorWidth = baseWidth, colorHeight = baseHeight;
|
|
||||||
QByteArray colorContents;
|
|
||||||
if (_color) {
|
|
||||||
colorWidth = _color->getWidth();
|
|
||||||
colorHeight = _color->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES);
|
|
||||||
colorContents = _color->getContents();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
colorContents = QByteArray(baseWidth * baseHeight * DataBlock::COLOR_BYTES, 0xFF);
|
|
||||||
}
|
|
||||||
|
|
||||||
int materialWidth = baseWidth, materialHeight = baseHeight;
|
|
||||||
QByteArray materialContents;
|
|
||||||
QVector<SharedObjectPointer> materials;
|
|
||||||
if (_material) {
|
|
||||||
materialWidth = _material->getWidth();
|
|
||||||
materialHeight = _material->getContents().size() / materialWidth;
|
|
||||||
materialContents = _material->getContents();
|
|
||||||
materials = _material->getMaterials();
|
|
||||||
|
|
||||||
} else {
|
|
||||||
materialContents = QByteArray(baseWidth * baseHeight, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
int highestX = colorWidth - 1;
|
|
||||||
int highestZ = colorHeight - 1;
|
|
||||||
glm::vec3 inverseScale(highestX / getScale(), 1.0f, highestZ / (getScale() * _aspectZ));
|
|
||||||
glm::vec3 center = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale;
|
|
||||||
|
|
||||||
glm::vec3 extents = glm::vec3(radius, radius, radius) * inverseScale;
|
|
||||||
glm::vec3 start = glm::floor(center - extents);
|
|
||||||
glm::vec3 end = glm::ceil(center + extents);
|
|
||||||
|
|
||||||
// paint all points within the radius
|
|
||||||
float z = qMax(start.z, 0.0f);
|
|
||||||
float startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX);
|
|
||||||
int stride = colorWidth * DataBlock::COLOR_BYTES;
|
|
||||||
uchar* lineDest = (uchar*)colorContents.data() + (int)z * stride + (int)startX * DataBlock::COLOR_BYTES;
|
|
||||||
float squaredRadius = extents.x * extents.x;
|
|
||||||
float multiplierZ = inverseScale.x / inverseScale.z;
|
|
||||||
char red = color.red(), green = color.green(), blue = color.blue();
|
|
||||||
bool changed = false;
|
|
||||||
for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) {
|
|
||||||
uchar* dest = lineDest;
|
|
||||||
for (float x = startX; x <= endX; x += 1.0f, dest += DataBlock::COLOR_BYTES) {
|
|
||||||
float dx = x - center.x, dz = (z - center.z) * multiplierZ;
|
|
||||||
if (dx * dx + dz * dz <= squaredRadius) {
|
|
||||||
dest[0] = red;
|
|
||||||
dest[1] = green;
|
|
||||||
dest[2] = blue;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lineDest += stride;
|
|
||||||
}
|
|
||||||
if (changed) {
|
|
||||||
newHeightfield->setColor(HeightfieldColorPointer(new HeightfieldColor(colorWidth, colorContents)));
|
|
||||||
}
|
|
||||||
|
|
||||||
highestX = materialWidth - 1;
|
|
||||||
highestZ = materialHeight - 1;
|
|
||||||
inverseScale = glm::vec3(highestX / getScale(), 1.0f, highestZ / (getScale() * _aspectZ));
|
|
||||||
center = glm::inverse(getRotation()) * (position - getTranslation()) * inverseScale;
|
|
||||||
|
|
||||||
extents = glm::vec3(radius, radius, radius) * inverseScale;
|
|
||||||
start = glm::floor(center - extents);
|
|
||||||
end = glm::ceil(center + extents);
|
|
||||||
|
|
||||||
// paint all points within the radius
|
|
||||||
z = qMax(start.z, 0.0f);
|
|
||||||
startX = qMax(start.x, 0.0f), endX = qMin(end.x, (float)highestX);
|
|
||||||
lineDest = (uchar*)materialContents.data() + (int)z * materialWidth + (int)startX;
|
|
||||||
squaredRadius = extents.x * extents.x;
|
|
||||||
uchar materialIndex = getMaterialIndex(material, materials, materialContents);
|
|
||||||
changed = false;
|
|
||||||
for (float endZ = qMin(end.z, (float)highestZ); z <= endZ; z += 1.0f) {
|
|
||||||
uchar* dest = lineDest;
|
|
||||||
for (float x = startX; x <= endX; x += 1.0f, dest++) {
|
|
||||||
float dx = x - center.x, dz = (z - center.z) * multiplierZ;
|
|
||||||
if (dx * dx + dz * dz <= squaredRadius) {
|
|
||||||
*dest = materialIndex;
|
|
||||||
changed = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
lineDest += materialWidth;
|
|
||||||
}
|
|
||||||
if (changed) {
|
|
||||||
clearUnusedMaterials(materials, materialContents);
|
|
||||||
newHeightfield->setMaterial(HeightfieldMaterialPointer(new HeightfieldMaterial(materialWidth,
|
|
||||||
materialContents, materials)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return newHeightfield;
|
return newHeightfield;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -497,18 +497,27 @@ public:
|
||||||
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
void setContents(const HeightfieldHeightPointer& height, const HeightfieldColorPointer& color,
|
||||||
const HeightfieldMaterialPointer& material);
|
const HeightfieldMaterialPointer& material);
|
||||||
|
|
||||||
|
void setHeight(const HeightfieldHeightPointer& height) { _height = height; }
|
||||||
const HeightfieldHeightPointer& getHeight() const { return _height; }
|
const HeightfieldHeightPointer& getHeight() const { return _height; }
|
||||||
|
|
||||||
|
void setColor(const HeightfieldColorPointer& color) { _color = color; }
|
||||||
const HeightfieldColorPointer& getColor() const { return _color; }
|
const HeightfieldColorPointer& getColor() const { return _color; }
|
||||||
|
|
||||||
|
void setMaterial(const HeightfieldMaterialPointer& material) { _material = material; }
|
||||||
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
const HeightfieldMaterialPointer& getMaterial() const { return _material; }
|
||||||
|
|
||||||
bool isLeaf() const;
|
bool isLeaf() const;
|
||||||
|
|
||||||
|
void setChild(int index, const HeightfieldNodePointer& child) { _children[index] = child; }
|
||||||
const HeightfieldNodePointer& getChild(int index) const { return _children[index]; }
|
const HeightfieldNodePointer& getChild(int index) const { return _children[index]; }
|
||||||
|
|
||||||
float getHeight(const glm::vec3& location) const;
|
float getHeight(const glm::vec3& location) const;
|
||||||
|
|
||||||
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance) const;
|
||||||
|
|
||||||
|
HeightfieldNode* paintMaterial(const glm::vec3& position, const glm::vec3& radius, const SharedObjectPointer& material,
|
||||||
|
const QColor& color);
|
||||||
|
|
||||||
void read(HeightfieldStreamState& state);
|
void read(HeightfieldStreamState& state);
|
||||||
void write(HeightfieldStreamState& state) const;
|
void write(HeightfieldStreamState& state) const;
|
||||||
|
|
||||||
|
@ -526,7 +535,7 @@ public:
|
||||||
private:
|
private:
|
||||||
|
|
||||||
void clearChildren();
|
void clearChildren();
|
||||||
void mergeChildren();
|
void mergeChildren(bool height = true, bool colorMaterial = true);
|
||||||
|
|
||||||
HeightfieldHeightPointer _height;
|
HeightfieldHeightPointer _height;
|
||||||
HeightfieldColorPointer _color;
|
HeightfieldColorPointer _color;
|
||||||
|
|
Loading…
Reference in a new issue