mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-04 11:25:18 +02:00
Closer to working edits.
This commit is contained in:
parent
377dc23dbe
commit
2711b3f312
3 changed files with 92 additions and 24 deletions
|
@ -2206,7 +2206,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
quint16* lineDest = dest;
|
||||
for (int x = 0; x < stackWidth; x++, src++, lineDest++) {
|
||||
if (!src->isEmpty()) {
|
||||
*lineDest = 0;
|
||||
//*lineDest = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1153,10 +1153,23 @@ static QVector<StackArray> decodeHeightfieldStack(const QByteArray& encoded,
|
|||
return contents;
|
||||
}
|
||||
|
||||
static inline bool isZero(const uchar values[4]) {
|
||||
return *(const quint32*)values == 0;
|
||||
}
|
||||
|
||||
bool StackArray::Entry::isZero() const {
|
||||
return ::isZero(rgba) && material == 0 && ::isZero(hermiteX) && ::isZero(hermiteY) && ::isZero(hermiteZ);
|
||||
}
|
||||
|
||||
bool StackArray::Entry::isMergeable(const Entry& other) const {
|
||||
return *(const quint32*)rgba == *(const quint32*)other.rgba && material == other.material &&
|
||||
::isZero(hermiteX) && ::isZero(hermiteY) && ::isZero(hermiteZ);
|
||||
}
|
||||
|
||||
void StackArray::Entry::setHermiteY(const glm::vec3& normal, float position) {
|
||||
hermiteY[0] = position * numeric_limits<qint8>::max();
|
||||
hermiteY[1] = position * numeric_limits<qint8>::max();
|
||||
hermiteY[2] = position * numeric_limits<qint8>::max();
|
||||
hermiteY[0] = normal.x * numeric_limits<qint8>::max();
|
||||
hermiteY[1] = normal.y * numeric_limits<qint8>::max();
|
||||
hermiteY[2] = normal.z * numeric_limits<qint8>::max();
|
||||
hermiteY[3] = position * numeric_limits<quint8>::max();
|
||||
}
|
||||
|
||||
|
@ -2168,12 +2181,22 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
|
||||
float colorX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerColorWidth / innerHeightWidth;
|
||||
float colorZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerColorHeight / innerHeightHeight;
|
||||
|
||||
uchar* colorDest = (colorX >= 0.0f && colorX <= innerColorWidth && colorZ >= 0.0f && colorZ <= innerColorHeight) ?
|
||||
((uchar*)newColorContents.data() + ((int)colorZ * colorWidth + (int)colorX) * DataBlock::COLOR_BYTES) : NULL;
|
||||
|
||||
float materialX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerMaterialWidth / innerHeightWidth;
|
||||
float materialZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerMaterialHeight / innerHeightHeight;
|
||||
|
||||
char* materialDest = (materialX >= 0.0f && materialX <= innerMaterialWidth && materialZ >= 0.0f &&
|
||||
materialZ <= innerMaterialHeight) ? (newMaterialContents.data() +
|
||||
(int)materialZ * materialWidth + (int)materialX) : NULL;
|
||||
|
||||
float stackX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerStackWidth / innerHeightWidth;
|
||||
float stackZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerStackHeight / innerHeightHeight;
|
||||
|
||||
int topHeight = -1;
|
||||
char topR = 0, topG = 0, topB = 0;
|
||||
uchar topMaterial;
|
||||
|
||||
if (stackX >= 0.0f && stackX <= innerStackWidth && stackZ >= 0.0f && stackZ <= innerStackHeight) {
|
||||
StackArray* stackDest = newStackContents.data() + (int)stackZ * stackWidth + (int)stackX;
|
||||
if (stackDest->isEmpty() && *heightLineDest != 0) {
|
||||
|
@ -2183,16 +2206,11 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
stackDest->setPosition(glm::floor(voxelHeight));
|
||||
StackArray::Entry* entryDest = stackDest->getEntryData();
|
||||
|
||||
if (colorX >= 0.0f && colorX <= innerColorWidth && colorZ >= 0.0f && colorZ <= innerColorHeight) {
|
||||
const uchar* colorDest = (const uchar*)newColorContents.constData() + ((int)colorZ * colorWidth +
|
||||
(int)colorX) * DataBlock::COLOR_BYTES;
|
||||
if (colorDest) {
|
||||
entryDest->setRGB(colorDest);
|
||||
}
|
||||
|
||||
if (materialX >= 0.0f && materialX <= innerMaterialWidth && materialZ >= 0.0f &&
|
||||
materialZ <= innerMaterialHeight) {
|
||||
const uchar* materialDest = (const uchar*)newMaterialContents.constData() +
|
||||
(int)materialZ * materialWidth + (int)materialX;
|
||||
if (materialDest) {
|
||||
int index = *materialDest;
|
||||
if (index != 0) {
|
||||
int& mapping = materialMappings[index];
|
||||
|
@ -2229,8 +2247,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
*stackDest = StackArray(newTop - newBottom + 1);
|
||||
stackDest->setPosition(newBottom);
|
||||
}
|
||||
quint16& stackPos = stackDest->getPositionRef();
|
||||
StackArray::Entry* entryDest = stackDest->getEntryData() + (newTop - stackPos);
|
||||
StackArray::Entry* entryDest = stackDest->getEntryData() + (newTop - stackDest->getPosition());
|
||||
glm::vec3 pos = glm::vec3(transform * glm::vec4(x, 0.0f, z, 1.0f)) + voxelStepY * (float)newTop;
|
||||
for (int y = newTop; y >= newBottom; y--, entryDest--, pos -= voxelStepY) {
|
||||
if (spanner->contains(pos)) {
|
||||
|
@ -2271,11 +2288,11 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
} else {
|
||||
bool intersects;
|
||||
if (erase == nextSetY) {
|
||||
if ((intersects = spanner->intersects(pos - voxelStepY, pos, distance, normal))) {
|
||||
if ((intersects = spanner->intersects(pos + voxelStepY, pos, distance, normal))) {
|
||||
distance = 1.0f - distance;
|
||||
}
|
||||
} else {
|
||||
intersects = spanner->intersects(pos, pos - voxelStepY, distance, normal);
|
||||
intersects = spanner->intersects(pos, pos + voxelStepY, distance, normal);
|
||||
}
|
||||
if (intersects) {
|
||||
if (erase) {
|
||||
|
@ -2291,9 +2308,59 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
|
||||
}
|
||||
}
|
||||
|
||||
// prune zero entries from end, repeated entries from beginning
|
||||
int endPruneCount = 0;
|
||||
for (int i = stackDest->getEntryCount() - 1; i >= 0 && stackDest->getEntryData()[i].isZero(); i--) {
|
||||
endPruneCount++;
|
||||
}
|
||||
if (endPruneCount == stackDest->getEntryCount()) {
|
||||
topHeight = 0;
|
||||
stackDest->clear();
|
||||
|
||||
} else {
|
||||
int topIndex = stackDest->getEntryCount() - 1;
|
||||
while (topIndex > 0 && !stackDest->getEntryData()[topIndex].isSet()) {
|
||||
topIndex--;
|
||||
}
|
||||
StackArray::Entry* topEntry = stackDest->getEntryData() + topIndex;
|
||||
if (topEntry->isSet()) {
|
||||
topHeight = ((stackDest->getPosition() + topIndex) +
|
||||
topEntry->hermiteY[3] / (float)numeric_limits<quint8>::max()) / voxelScale;
|
||||
topR = topEntry->rgba[0];
|
||||
topG = topEntry->rgba[1];
|
||||
topB = topEntry->rgba[2];
|
||||
topMaterial = topEntry->material;
|
||||
|
||||
} else {
|
||||
topHeight = 0;
|
||||
}
|
||||
stackDest->removeEntries(stackDest->getEntryCount() - endPruneCount, endPruneCount);
|
||||
int beginningPruneCount = 0;
|
||||
for (int i = 0; i < stackDest->getEntryCount() - 1 && stackDest->getEntryData()[i].isMergeable(
|
||||
stackDest->getEntryData()[i + 1]); i++) {
|
||||
beginningPruneCount++;
|
||||
}
|
||||
stackDest->removeEntries(0, beginningPruneCount);
|
||||
stackDest->getPositionRef() += beginningPruneCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (erase) {
|
||||
if (topHeight != -1) {
|
||||
*heightLineDest = topHeight;
|
||||
if (colorDest) {
|
||||
colorDest[0] = topR;
|
||||
colorDest[1] = topG;
|
||||
colorDest[2] = topB;
|
||||
}
|
||||
if (materialDest) {
|
||||
if (topMaterial != 0) {
|
||||
topMaterial = getMaterialIndex(newStackMaterials.at(topMaterial - 1),
|
||||
newMaterialMaterials, newMaterialContents);
|
||||
}
|
||||
*materialDest = topMaterial;
|
||||
}
|
||||
} else if (erase) {
|
||||
if (spanner->intersects(endPos, worldPos, distance, normal)) {
|
||||
quint16 height = glm::round(glm::mix(end.y, start.y, distance));
|
||||
if (height <= *heightLineDest) {
|
||||
|
@ -2305,9 +2372,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
if (height >= *heightLineDest) {
|
||||
*heightLineDest = height;
|
||||
|
||||
if (colorX >= 0.0f && colorX <= innerColorWidth && colorZ >= 0.0f && colorZ <= innerColorHeight) {
|
||||
char* colorDest = newColorContents.data() + ((int)colorZ * colorWidth +
|
||||
(int)colorX) * DataBlock::COLOR_BYTES;
|
||||
if (colorDest) {
|
||||
if (hasOwnColors) {
|
||||
QRgb spannerColor = spanner->getColorAt(glm::mix(endPos, worldPos, distance));
|
||||
colorDest[0] = qRed(spannerColor);
|
||||
|
@ -2321,9 +2386,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
}
|
||||
}
|
||||
|
||||
if (materialX >= 0.0f && materialX <= innerMaterialWidth && materialZ >= 0.0f &&
|
||||
materialZ <= innerMaterialHeight) {
|
||||
char* materialDest = newMaterialContents.data() + (int)materialZ * materialWidth + (int)materialX;
|
||||
if (materialDest) {
|
||||
if (hasOwnMaterials) {
|
||||
int index = spanner->getMaterialAt(glm::mix(endPos, worldPos, distance));
|
||||
if (index != 0) {
|
||||
|
|
|
@ -490,6 +490,9 @@ public:
|
|||
|
||||
bool isSet() const { return rgba[3] != 0; }
|
||||
|
||||
bool isZero() const;
|
||||
bool isMergeable(const Entry& other) const;
|
||||
|
||||
void setHermiteY(int x, int y, int z, int w) { hermiteY[0] = x; hermiteY[1] = y; hermiteY[2] = z; hermiteY[3] = w; }
|
||||
void setHermiteY(const glm::vec3& normal, float position);
|
||||
void clearHermiteY() { setHermiteY(0, 0, 0, 0); }
|
||||
|
@ -512,6 +515,8 @@ public:
|
|||
|
||||
Entry* getEntryData() { return (Entry*)(data() + sizeof(quint16)); }
|
||||
const Entry* getEntryData() const { return (const Entry*)(constData() + sizeof(quint16)); }
|
||||
|
||||
void removeEntries(int position, int count) { remove(sizeof(quint16) + position * sizeof(Entry), count * sizeof(Entry)); }
|
||||
};
|
||||
|
||||
/// A block of stack data associated with a heightfield.
|
||||
|
|
Loading…
Reference in a new issue