mirror of
https://github.com/overte-org/overte.git
synced 2025-08-17 09:15:37 +02:00
Stitching improvement.
This commit is contained in:
parent
dfbc3502fa
commit
d002359989
2 changed files with 110 additions and 115 deletions
|
@ -1847,34 +1847,32 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
NormalIndex index = { { vertices.size(), vertices.size(), vertices.size(), vertices.size() } };
|
||||
if (stitch) {
|
||||
// pack the corners set into a set of flags
|
||||
int corners = 0;
|
||||
glm::vec2 position;
|
||||
int count = 0;
|
||||
for (int i = 0; i < crossingCount; i++) {
|
||||
const EdgeCrossing& crossing = crossings[i];
|
||||
if (qAlpha(crossing.color) == 0) {
|
||||
int corner = (crossing.point.x == 1.0f) | ((crossing.point.z == 1.0f) << 1);
|
||||
corners |= (1 << corner);
|
||||
position += glm::vec2(crossing.point.x, crossing.point.z);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// fall into four cases based on set corners
|
||||
int offsetX = 0, offsetZ = 0;
|
||||
switch(corners) {
|
||||
case 3:
|
||||
case 11: // z- edge, x+/z- corner
|
||||
offsetX = 1;
|
||||
break;
|
||||
|
||||
case 12:
|
||||
case 13: // z+ edge, x-/z+ corner
|
||||
offsetZ = 1;
|
||||
break;
|
||||
|
||||
case 10:
|
||||
case 14: // x+ edge, x+/z+ corner
|
||||
offsetX = offsetZ = 1;
|
||||
break;
|
||||
position /= count;
|
||||
|
||||
const int CORNER_COUNT = 4;
|
||||
float closestDistance = FLT_MAX;
|
||||
int closestOffsetX = 0;
|
||||
int closestOffsetZ = 0;
|
||||
for (int i = 0; i < CORNER_COUNT; i++) {
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
float distance = glm::distance(position, glm::vec2(offsetX, offsetZ));
|
||||
if (distance < closestDistance && heightLineSrc[width * offsetZ + offsetX] != 0) {
|
||||
closestDistance = distance;
|
||||
closestOffsetX = offsetX;
|
||||
closestOffsetZ = offsetZ;
|
||||
}
|
||||
}
|
||||
const quint16* height = heightLineSrc + width * offsetZ + offsetX;
|
||||
const quint16* height = heightLineSrc + width * closestOffsetZ + closestOffsetX;
|
||||
int left = height[-1];
|
||||
int right = height[1];
|
||||
int down = height[-width];
|
||||
|
@ -1884,7 +1882,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
quint8 red = numeric_limits<quint8>::max();
|
||||
quint8 green = numeric_limits<quint8>::max();
|
||||
quint8 blue = numeric_limits<quint8>::max();
|
||||
int clampedOffsetX = clampedX + offsetX, clampedOffsetZ = clampedZ + offsetZ;
|
||||
int clampedOffsetX = clampedX + closestOffsetX, clampedOffsetZ = clampedZ + closestOffsetZ;
|
||||
if (colorSrc) {
|
||||
const uchar* color = colorSrc + ((int)(clampedOffsetZ * colorStepZ) * colorWidth +
|
||||
(int)(clampedOffsetX * colorStepX)) * DataBlock::COLOR_BYTES;
|
||||
|
@ -1905,8 +1903,8 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
material = mapping;
|
||||
}
|
||||
}
|
||||
VoxelPoint point = { glm::vec3(clampedX + offsetX, *height * voxelScale,
|
||||
clampedZ + offsetZ) * step, { red, green, blue },
|
||||
VoxelPoint point = { glm::vec3(clampedOffsetX, *height * voxelScale, clampedOffsetZ) * step,
|
||||
{ red, green, blue },
|
||||
{ (char)(normal.x * numeric_limits<qint8>::max()),
|
||||
(char)(normal.y * numeric_limits<qint8>::max()),
|
||||
(char)(normal.z * numeric_limits<qint8>::max()) }, { material, 0, 0, 0 },
|
||||
|
|
|
@ -2827,6 +2827,93 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) {
|
|||
} else if (height) {
|
||||
_height.reset();
|
||||
}
|
||||
if (colorWidth > 0 && colorMaterial) {
|
||||
QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF);
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
HeightfieldColorPointer childColor = _children[i]->getColor();
|
||||
if (!childColor) {
|
||||
continue;
|
||||
}
|
||||
int childColorWidth = childColor->getWidth();
|
||||
int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES);
|
||||
if (childColorWidth != colorWidth || childColorHeight != colorHeight) {
|
||||
qWarning() << "Color dimension mismatch [colorWidth=" << colorWidth << ", colorHeight=" << colorHeight <<
|
||||
", childColorWidth=" << childColorWidth << ", childColorHeight=" << childColorHeight << "]";
|
||||
continue;
|
||||
}
|
||||
int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE;
|
||||
int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE;
|
||||
int innerQuadrantColorWidth = innerColorWidth / 2;
|
||||
int innerQuadrantColorHeight = innerColorHeight / 2;
|
||||
int quadrantColorWidth = innerQuadrantColorWidth + HeightfieldData::SHARED_EDGE;
|
||||
int quadrantColorHeight = innerQuadrantColorHeight + HeightfieldData::SHARED_EDGE;
|
||||
char* dest = colorContents.data() + ((i & Y_MAXIMUM_FLAG ? innerQuadrantColorHeight * colorWidth : 0) +
|
||||
(i & X_MAXIMUM_FLAG ? innerQuadrantColorWidth : 0)) * DataBlock::COLOR_BYTES;
|
||||
const uchar* src = (const uchar*)childColor->getContents().constData();
|
||||
for (int z = 0; z < quadrantColorHeight; z++, dest += colorWidth * DataBlock::COLOR_BYTES,
|
||||
src += colorWidth * DataBlock::COLOR_BYTES * 2) {
|
||||
const uchar* lineSrc = src;
|
||||
for (char* lineDest = dest, *end = dest + quadrantColorWidth * DataBlock::COLOR_BYTES;
|
||||
lineDest != end; lineDest += DataBlock::COLOR_BYTES, lineSrc += DataBlock::COLOR_BYTES * 2) {
|
||||
lineDest[0] = lineSrc[0];
|
||||
lineDest[1] = lineSrc[1];
|
||||
lineDest[2] = lineSrc[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
_color = new HeightfieldColor(colorWidth, colorContents);
|
||||
|
||||
} else {
|
||||
_color.reset();
|
||||
}
|
||||
if (materialWidth > 0 && colorMaterial) {
|
||||
QByteArray materialContents(materialWidth * materialHeight, 0);
|
||||
QVector<SharedObjectPointer> materials;
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial();
|
||||
if (!childMaterial) {
|
||||
continue;
|
||||
}
|
||||
int childMaterialWidth = childMaterial->getWidth();
|
||||
int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth;
|
||||
if (childMaterialWidth != materialWidth || childMaterialHeight != materialHeight) {
|
||||
qWarning() << "Material dimension mismatch [materialWidth=" << materialWidth << ", materialHeight=" <<
|
||||
materialHeight << ", childMaterialWidth=" << childMaterialWidth << ", childMaterialHeight=" <<
|
||||
childMaterialHeight << "]";
|
||||
continue;
|
||||
}
|
||||
int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE;
|
||||
int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE;
|
||||
int innerQuadrantMaterialWidth = innerMaterialWidth / 2;
|
||||
int innerQuadrantMaterialHeight = innerMaterialHeight / 2;
|
||||
int quadrantMaterialWidth = innerQuadrantMaterialWidth + HeightfieldData::SHARED_EDGE;
|
||||
int quadrantMaterialHeight = innerQuadrantMaterialHeight + HeightfieldData::SHARED_EDGE;
|
||||
uchar* dest = (uchar*)materialContents.data() +
|
||||
(i & Y_MAXIMUM_FLAG ? innerQuadrantMaterialHeight * materialWidth : 0) +
|
||||
(i & X_MAXIMUM_FLAG ? innerQuadrantMaterialWidth : 0);
|
||||
const uchar* src = (const uchar*)childMaterial->getContents().constData();
|
||||
QHash<int, int> materialMap;
|
||||
for (int z = 0; z < quadrantMaterialHeight; z++, dest += materialWidth, src += materialWidth * 2) {
|
||||
const uchar* lineSrc = src;
|
||||
for (uchar* lineDest = dest, *end = dest + quadrantMaterialWidth; lineDest != end; lineDest++, lineSrc += 2) {
|
||||
int value = *lineSrc;
|
||||
if (value != 0) {
|
||||
int& mapping = materialMap[value];
|
||||
if (mapping == 0) {
|
||||
mapping = getMaterialIndex(childMaterial->getMaterials().at(value - 1),
|
||||
materials, materialContents);
|
||||
}
|
||||
value = mapping;
|
||||
}
|
||||
*lineDest = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
_material = new HeightfieldMaterial(materialWidth, materialContents, materials);
|
||||
|
||||
} else {
|
||||
_material.reset();
|
||||
}
|
||||
if (stackWidth > 0) {
|
||||
QVector<StackArray> stackContents(stackWidth * stackHeight);
|
||||
QVector<SharedObjectPointer> stackMaterials;
|
||||
|
@ -2918,96 +3005,6 @@ void HeightfieldNode::mergeChildren(bool height, bool colorMaterial) {
|
|||
} else {
|
||||
_stack.reset();
|
||||
}
|
||||
if (!colorMaterial) {
|
||||
return;
|
||||
}
|
||||
if (colorWidth > 0) {
|
||||
QByteArray colorContents(colorWidth * colorHeight * DataBlock::COLOR_BYTES, 0xFF);
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
HeightfieldColorPointer childColor = _children[i]->getColor();
|
||||
if (!childColor) {
|
||||
continue;
|
||||
}
|
||||
int childColorWidth = childColor->getWidth();
|
||||
int childColorHeight = childColor->getContents().size() / (childColorWidth * DataBlock::COLOR_BYTES);
|
||||
if (childColorWidth != colorWidth || childColorHeight != colorHeight) {
|
||||
qWarning() << "Color dimension mismatch [colorWidth=" << colorWidth << ", colorHeight=" << colorHeight <<
|
||||
", childColorWidth=" << childColorWidth << ", childColorHeight=" << childColorHeight << "]";
|
||||
continue;
|
||||
}
|
||||
int innerColorWidth = colorWidth - HeightfieldData::SHARED_EDGE;
|
||||
int innerColorHeight = colorHeight - HeightfieldData::SHARED_EDGE;
|
||||
int innerQuadrantColorWidth = innerColorWidth / 2;
|
||||
int innerQuadrantColorHeight = innerColorHeight / 2;
|
||||
int quadrantColorWidth = innerQuadrantColorWidth + HeightfieldData::SHARED_EDGE;
|
||||
int quadrantColorHeight = innerQuadrantColorHeight + HeightfieldData::SHARED_EDGE;
|
||||
char* dest = colorContents.data() + ((i & Y_MAXIMUM_FLAG ? innerQuadrantColorHeight * colorWidth : 0) +
|
||||
(i & X_MAXIMUM_FLAG ? innerQuadrantColorWidth : 0)) * DataBlock::COLOR_BYTES;
|
||||
const uchar* src = (const uchar*)childColor->getContents().constData();
|
||||
for (int z = 0; z < quadrantColorHeight; z++, dest += colorWidth * DataBlock::COLOR_BYTES,
|
||||
src += colorWidth * DataBlock::COLOR_BYTES * 2) {
|
||||
const uchar* lineSrc = src;
|
||||
for (char* lineDest = dest, *end = dest + quadrantColorWidth * DataBlock::COLOR_BYTES;
|
||||
lineDest != end; lineDest += DataBlock::COLOR_BYTES, lineSrc += DataBlock::COLOR_BYTES * 2) {
|
||||
lineDest[0] = lineSrc[0];
|
||||
lineDest[1] = lineSrc[1];
|
||||
lineDest[2] = lineSrc[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
_color = new HeightfieldColor(colorWidth, colorContents);
|
||||
|
||||
} else {
|
||||
_color.reset();
|
||||
}
|
||||
if (materialWidth > 0) {
|
||||
QByteArray materialContents(materialWidth * materialHeight, 0);
|
||||
QVector<SharedObjectPointer> materials;
|
||||
for (int i = 0; i < CHILD_COUNT; i++) {
|
||||
HeightfieldMaterialPointer childMaterial = _children[i]->getMaterial();
|
||||
if (!childMaterial) {
|
||||
continue;
|
||||
}
|
||||
int childMaterialWidth = childMaterial->getWidth();
|
||||
int childMaterialHeight = childMaterial->getContents().size() / childMaterialWidth;
|
||||
if (childMaterialWidth != materialWidth || childMaterialHeight != materialHeight) {
|
||||
qWarning() << "Material dimension mismatch [materialWidth=" << materialWidth << ", materialHeight=" <<
|
||||
materialHeight << ", childMaterialWidth=" << childMaterialWidth << ", childMaterialHeight=" <<
|
||||
childMaterialHeight << "]";
|
||||
continue;
|
||||
}
|
||||
int innerMaterialWidth = materialWidth - HeightfieldData::SHARED_EDGE;
|
||||
int innerMaterialHeight = materialHeight - HeightfieldData::SHARED_EDGE;
|
||||
int innerQuadrantMaterialWidth = innerMaterialWidth / 2;
|
||||
int innerQuadrantMaterialHeight = innerMaterialHeight / 2;
|
||||
int quadrantMaterialWidth = innerQuadrantMaterialWidth + HeightfieldData::SHARED_EDGE;
|
||||
int quadrantMaterialHeight = innerQuadrantMaterialHeight + HeightfieldData::SHARED_EDGE;
|
||||
uchar* dest = (uchar*)materialContents.data() +
|
||||
(i & Y_MAXIMUM_FLAG ? innerQuadrantMaterialHeight * materialWidth : 0) +
|
||||
(i & X_MAXIMUM_FLAG ? innerQuadrantMaterialWidth : 0);
|
||||
const uchar* src = (const uchar*)childMaterial->getContents().constData();
|
||||
QHash<int, int> materialMap;
|
||||
for (int z = 0; z < quadrantMaterialHeight; z++, dest += materialWidth, src += materialWidth * 2) {
|
||||
const uchar* lineSrc = src;
|
||||
for (uchar* lineDest = dest, *end = dest + quadrantMaterialWidth; lineDest != end; lineDest++, lineSrc += 2) {
|
||||
int value = *lineSrc;
|
||||
if (value != 0) {
|
||||
int& mapping = materialMap[value];
|
||||
if (mapping == 0) {
|
||||
mapping = getMaterialIndex(childMaterial->getMaterials().at(value - 1),
|
||||
materials, materialContents);
|
||||
}
|
||||
value = mapping;
|
||||
}
|
||||
*lineDest = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
_material = new HeightfieldMaterial(materialWidth, materialContents, materials);
|
||||
|
||||
} else {
|
||||
_material.reset();
|
||||
}
|
||||
}
|
||||
|
||||
QRgb HeightfieldNode::getColorAt(const glm::vec3& location) const {
|
||||
|
|
Loading…
Reference in a new issue