mirror of
https://github.com/overte-org/overte.git
synced 2025-04-21 06:44:06 +02:00
More progress on rendering.
This commit is contained in:
parent
135e3bf574
commit
de4776ef08
3 changed files with 138 additions and 59 deletions
|
@ -2294,6 +2294,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
glm::vec3 step(1.0f / innerStackWidth, scale.x / (innerStackWidth * scale.y),
|
||||
1.0f / innerStackHeight);
|
||||
|
||||
const int EDGES_PER_CUBE = 12;
|
||||
EdgeCrossing crossings[EDGES_PER_CUBE];
|
||||
|
||||
for (int z = 0; z <= stackHeight; z++) {
|
||||
pos.x = 0.0f;
|
||||
const StackArray* lineSrc = src;
|
||||
|
@ -2324,9 +2327,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
hermiteSegments.append(start + normal * step);
|
||||
}
|
||||
}
|
||||
int alpha0 = entry->rgba[3];
|
||||
int alpha0 = qAlpha(entry->color);
|
||||
int alpha2 = lineSrc->getEntryAlpha(y + 1);
|
||||
int alpha1 = alpha0, alpha4 = alpha0, alpha6 = alpha0;
|
||||
int alpha1 = alpha0, alpha3 = alpha2, alpha4 = alpha0, alpha6 = alpha2;
|
||||
int alphaTotal = alpha0 + alpha2;
|
||||
int possibleTotal = 2 * numeric_limits<uchar>::max();
|
||||
|
||||
|
@ -2341,10 +2344,73 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
alphaTotal += (alpha6 = lineSrc[stackWidth].getEntryAlpha(y + 1));
|
||||
possibleTotal += numeric_limits<uchar>::max();
|
||||
}
|
||||
|
||||
int alpha5 = alpha4, alpha7 = alpha6;
|
||||
if (middleX) {
|
||||
alphaTotal += (alpha1 = lineSrc[1].getEntryAlpha(y));
|
||||
possibleTotal += numeric_limits<uchar>::max();
|
||||
|
||||
alphaTotal += (alpha3 = lineSrc[1].getEntryAlpha(y + 1));
|
||||
possibleTotal += numeric_limits<uchar>::max();
|
||||
|
||||
if (middleZ) {
|
||||
alphaTotal += (alpha5 = lineSrc[stackWidth + 1].getEntryAlpha(y));
|
||||
possibleTotal += numeric_limits<uchar>::max();
|
||||
|
||||
alphaTotal += (alpha7 = lineSrc[stackWidth + 1].getEntryAlpha(y + 1));
|
||||
possibleTotal += numeric_limits<uchar>::max();
|
||||
}
|
||||
}
|
||||
if (alphaTotal == 0 || alphaTotal == possibleTotal) {
|
||||
continue; // no corners set/all corners set
|
||||
}
|
||||
// the terrifying conditional code that follows checks each cube edge for a crossing, gathering
|
||||
// its properties (color, material, normal) if one is present; as before, boundary edges are excluded
|
||||
int crossingCount = 0;
|
||||
if (middleX) {
|
||||
if (alpha0 != alpha1) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
float distance = entry->getHermiteX(crossing.normal);
|
||||
if (alpha0 == 0) {
|
||||
const StackArray::Entry& nextEntry = lineSrc[1].getEntry(y);
|
||||
crossing.color = nextEntry.color;
|
||||
crossing.material = nextEntry.material;
|
||||
} else {
|
||||
crossing.color = entry->color;
|
||||
crossing.material = entry->material;
|
||||
}
|
||||
crossing.point = glm::vec3(distance, 0.0f, 0.0f);
|
||||
}
|
||||
|
||||
}
|
||||
if (alpha0 != alpha2) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
float distance = entry->getHermiteY(crossing.normal);
|
||||
if (alpha0 == 0) {
|
||||
const StackArray::Entry& nextEntry = lineSrc->getEntry(y + 1);
|
||||
crossing.color = nextEntry.color;
|
||||
crossing.material = nextEntry.material;
|
||||
} else {
|
||||
crossing.color = entry->color;
|
||||
crossing.material = entry->material;
|
||||
}
|
||||
crossing.point = glm::vec3(0.0f, distance, 0.0f);
|
||||
}
|
||||
if (middleZ) {
|
||||
if (alpha0 != alpha4) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
float distance = entry->getHermiteZ(crossing.normal);
|
||||
if (alpha0 == 0) {
|
||||
const StackArray::Entry& nextEntry = lineSrc[stackWidth].getEntry(y);
|
||||
crossing.color = nextEntry.color;
|
||||
crossing.material = nextEntry.material;
|
||||
} else {
|
||||
crossing.color = entry->color;
|
||||
crossing.material = entry->material;
|
||||
}
|
||||
crossing.point = glm::vec3(0.0f, 0.0f, distance);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if (x != 0) {
|
||||
|
|
|
@ -1153,31 +1153,32 @@ static QVector<StackArray> decodeHeightfieldStack(const QByteArray& encoded,
|
|||
return contents;
|
||||
}
|
||||
|
||||
static inline bool isZero(const uchar values[4]) {
|
||||
return *(const quint32*)values == 0;
|
||||
StackArray::Entry::Entry() :
|
||||
color(0),
|
||||
material(0),
|
||||
hermiteX(0),
|
||||
hermiteY(0),
|
||||
hermiteZ(0) {
|
||||
}
|
||||
|
||||
bool StackArray::Entry::isZero() const {
|
||||
return ::isZero(rgba) && material == 0 && ::isZero(hermiteX) && ::isZero(hermiteY) && ::isZero(hermiteZ);
|
||||
return color == 0 && material == 0 && hermiteX == 0 && hermiteY == 0 && hermiteZ == 0;
|
||||
}
|
||||
|
||||
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);
|
||||
return color == other.color && material == other.material && hermiteX == 0 && hermiteY == 0 && hermiteZ == 0;
|
||||
}
|
||||
|
||||
static inline void setHermite(uchar values[4], const glm::vec3& normal, float position) {
|
||||
values[0] = normal.x * numeric_limits<qint8>::max();
|
||||
values[1] = normal.y * numeric_limits<qint8>::max();
|
||||
values[2] = normal.z * numeric_limits<qint8>::max();
|
||||
values[3] = position * numeric_limits<quint8>::max();
|
||||
static inline void setHermite(quint32& value, const glm::vec3& normal, float position) {
|
||||
value = qRgba(normal.x * numeric_limits<qint8>::max(), normal.y * numeric_limits<qint8>::max(),
|
||||
normal.z * numeric_limits<qint8>::max(), position * numeric_limits<quint8>::max());
|
||||
}
|
||||
|
||||
static inline float getHermite(const uchar values[4], glm::vec3& normal) {
|
||||
normal.x = (char)values[0] / (float)numeric_limits<qint8>::max();
|
||||
normal.y = (char)values[1] / (float)numeric_limits<qint8>::max();
|
||||
normal.z = (char)values[2] / (float)numeric_limits<qint8>::max();
|
||||
return values[3] / (float)numeric_limits<qint8>::max();
|
||||
static inline float getHermite(QRgb value, glm::vec3& normal) {
|
||||
normal.x = (char)qRed(value) / (float)numeric_limits<qint8>::max();
|
||||
normal.y = (char)qGreen(value) / (float)numeric_limits<qint8>::max();
|
||||
normal.z = (char)qBlue(value) / (float)numeric_limits<qint8>::max();
|
||||
return qAlpha(value) / (float)numeric_limits<qint8>::max();
|
||||
}
|
||||
|
||||
void StackArray::Entry::setHermiteX(const glm::vec3& normal, float position) {
|
||||
|
@ -1210,7 +1211,27 @@ int StackArray::getEntryAlpha(int y) const {
|
|||
return 0;
|
||||
}
|
||||
int relative = y - getPosition();
|
||||
return (relative < count) ? getEntryData()[qMax(relative, 0)].rgba[3] : 0;
|
||||
return (relative < count) ? qAlpha(getEntryData()[qMax(relative, 0)].color) : 0;
|
||||
}
|
||||
|
||||
StackArray::Entry& StackArray::getEntry(int y) {
|
||||
static Entry emptyEntry;
|
||||
int count = getEntryCount();
|
||||
if (count == 0) {
|
||||
return emptyEntry;
|
||||
}
|
||||
int relative = y - getPosition();
|
||||
return (relative < count) ? getEntryData()[qMax(relative, 0)] : emptyEntry;
|
||||
}
|
||||
|
||||
const StackArray::Entry& StackArray::getEntry(int y) const {
|
||||
static Entry emptyEntry;
|
||||
int count = getEntryCount();
|
||||
if (count == 0) {
|
||||
return emptyEntry;
|
||||
}
|
||||
int relative = y - getPosition();
|
||||
return (relative < count) ? getEntryData()[qMax(relative, 0)] : emptyEntry;
|
||||
}
|
||||
|
||||
HeightfieldStack::HeightfieldStack(int width, const QVector<StackArray>& contents,
|
||||
|
@ -2214,8 +2235,8 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
glm::vec3 voxelStepZ = glm::vec3(transform * glm::vec4(0.0f, 0.0f, 1.0f, 0.0f));
|
||||
int newTop = start.y * voxelScale;
|
||||
int newBottom = end.y * voxelScale;
|
||||
char r = color.red(), g = color.green(), b = color.blue(), a = color.alpha();
|
||||
bool erase = (a == 0);
|
||||
QRgb rgba = color.rgba();
|
||||
bool erase = (color.alpha() == 0);
|
||||
uchar materialMaterialIndex = getMaterialIndex(material, newMaterialMaterials, newMaterialContents);
|
||||
QByteArray dummyContents;
|
||||
uchar stackMaterialIndex = getMaterialIndex(material, newStackMaterials, dummyContents);
|
||||
|
@ -2246,8 +2267,8 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
float stackZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerStackHeight / innerHeightHeight;
|
||||
|
||||
int topHeight = -1;
|
||||
char topR = 0, topG = 0, topB = 0;
|
||||
uchar topMaterial;
|
||||
QRgb topColor = 0;
|
||||
uchar topMaterial = 0;
|
||||
|
||||
if (stackX >= 0.0f && stackX <= innerStackWidth && stackZ >= 0.0f && stackZ <= innerStackHeight) {
|
||||
StackArray* stackDest = newStackContents.data() + (int)stackZ * stackWidth + (int)stackX;
|
||||
|
@ -2259,7 +2280,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
StackArray::Entry* entryDest = stackDest->getEntryData();
|
||||
|
||||
if (colorDest) {
|
||||
entryDest->setRGB(colorDest);
|
||||
entryDest->color = qRgb(colorDest[0], colorDest[1], colorDest[2]);
|
||||
}
|
||||
|
||||
if (materialDest) {
|
||||
|
@ -2295,7 +2316,7 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
stackDest->getEntryCount() * sizeof(StackArray::Entry));
|
||||
for (StackArray::Entry* entryDest = newStack.getEntryData(), *end = entryDest + prepend;
|
||||
entryDest != end; entryDest++) {
|
||||
entryDest->setRGBA(end->rgba);
|
||||
entryDest->color = end->color;
|
||||
entryDest->material = end->material;
|
||||
}
|
||||
*stackDest = newStack;
|
||||
|
@ -2311,10 +2332,10 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
bool oldCurrentSet = entryDest->isSet();
|
||||
if (spanner->contains(pos)) {
|
||||
if (hasOwnColors && !erase) {
|
||||
entryDest->setRGBA(spanner->getColorAt(pos));
|
||||
entryDest->color = spanner->getColorAt(pos);
|
||||
|
||||
} else {
|
||||
entryDest->setRGBA(r, g, b, a);
|
||||
entryDest->color = rgba;
|
||||
}
|
||||
if (hasOwnMaterials && !erase) {
|
||||
int index = spanner->getMaterialAt(pos);
|
||||
|
@ -2337,14 +2358,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
if (nextStackX <= innerStackWidth) {
|
||||
bool nextSetX = isSet(newStackContents, stackWidth, nextStackX, y, (int)stackZ);
|
||||
if (nextSetX == currentSet) {
|
||||
entryDest->clearHermiteX();
|
||||
entryDest->hermiteX = 0;
|
||||
|
||||
} else {
|
||||
bool flipped = (erase == nextSetX);
|
||||
float oldDistance = flipped ? 0.0f : 1.0f;
|
||||
if (currentSet == oldCurrentSet && nextSetX == isSet(oldStackContents, stackWidth,
|
||||
nextStackX, y, (int)stackZ)) {
|
||||
oldDistance = entryDest->hermiteX[3] / (float)numeric_limits<quint8>::max();
|
||||
oldDistance = qAlpha(entryDest->hermiteX) / (float)numeric_limits<quint8>::max();
|
||||
}
|
||||
if (flipped ? (spanner->intersects(pos + voxelStepX, pos, distance, normal) &&
|
||||
(distance = 1.0f - distance) >= oldDistance) :
|
||||
|
@ -2357,14 +2378,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
bool nextSetY = (entryDest != stackDest->getEntryData() + stackDest->getEntryCount() - 1 &&
|
||||
(entryDest + 1)->isSet());
|
||||
if (nextSetY == currentSet) {
|
||||
entryDest->clearHermiteY();
|
||||
entryDest->hermiteY = 0;
|
||||
|
||||
} else {
|
||||
bool flipped = (erase == nextSetY);
|
||||
float oldDistance = flipped ? 0.0f : 1.0f;
|
||||
if (currentSet == oldCurrentSet && nextSetY == isSet(oldStackContents, stackWidth,
|
||||
(int)stackX, y + 1, (int)stackZ)) {
|
||||
oldDistance = entryDest->hermiteY[3] / (float)numeric_limits<quint8>::max();
|
||||
oldDistance = qAlpha(entryDest->hermiteY) / (float)numeric_limits<quint8>::max();
|
||||
}
|
||||
if (flipped ? (spanner->intersects(pos + voxelStepY, pos, distance, normal) &&
|
||||
(distance = 1.0f - distance) >= oldDistance) :
|
||||
|
@ -2377,14 +2398,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
if (nextStackZ <= innerStackHeight) {
|
||||
bool nextSetZ = isSet(newStackContents, stackWidth, (int)stackX, y, nextStackZ);
|
||||
if (nextSetZ == currentSet) {
|
||||
entryDest->clearHermiteZ();
|
||||
entryDest->hermiteZ = 0;
|
||||
|
||||
} else {
|
||||
bool flipped = (erase == nextSetZ);
|
||||
float oldDistance = flipped ? 0.0f : 1.0f;
|
||||
if (currentSet == oldCurrentSet && nextSetZ == isSet(oldStackContents, stackWidth,
|
||||
(int)stackX, y, nextStackZ)) {
|
||||
oldDistance = entryDest->hermiteZ[3] / (float)numeric_limits<quint8>::max();
|
||||
oldDistance = qAlpha(entryDest->hermiteZ) / (float)numeric_limits<quint8>::max();
|
||||
}
|
||||
if (flipped ? (spanner->intersects(pos + voxelStepZ, pos, distance, normal) &&
|
||||
(distance = 1.0f - distance) >= oldDistance) :
|
||||
|
@ -2413,10 +2434,8 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
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];
|
||||
qAlpha(topEntry->hermiteY) / (float)numeric_limits<quint8>::max()) / voxelScale;
|
||||
topColor = topEntry->color;
|
||||
topMaterial = topEntry->material;
|
||||
|
||||
} else {
|
||||
|
@ -2436,9 +2455,9 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
if (topHeight != -1) {
|
||||
*heightLineDest = topHeight;
|
||||
if (colorDest) {
|
||||
colorDest[0] = topR;
|
||||
colorDest[1] = topG;
|
||||
colorDest[2] = topB;
|
||||
colorDest[0] = qRed(topColor);
|
||||
colorDest[1] = qGreen(topColor);
|
||||
colorDest[2] = qBlue(topColor);
|
||||
}
|
||||
if (materialDest) {
|
||||
if (topMaterial != 0) {
|
||||
|
@ -2467,9 +2486,9 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
colorDest[2] = qBlue(spannerColor);
|
||||
|
||||
} else {
|
||||
colorDest[0] = r;
|
||||
colorDest[1] = g;
|
||||
colorDest[2] = b;
|
||||
colorDest[0] = color.red();
|
||||
colorDest[1] = color.green();
|
||||
colorDest[2] = color.blue();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -477,35 +477,26 @@ public:
|
|||
/// A single entry within the array.
|
||||
class Entry {
|
||||
public:
|
||||
uchar rgba[4];
|
||||
quint32 color;
|
||||
uchar material;
|
||||
uchar hermiteX[4];
|
||||
uchar hermiteY[4];
|
||||
uchar hermiteZ[4];
|
||||
|
||||
void setRGBA(int r, int g, int b, int a = 0xFF) { rgba[0] = r; rgba[1] = g; rgba[2] = b; rgba[3] = a; }
|
||||
void setRGBA(const uchar* orgba) { setRGBA(orgba[0], orgba[1], orgba[2], orgba[3]); }
|
||||
void setRGB(const uchar* rgb) { setRGBA(rgb[0], rgb[1], rgb[2]); }
|
||||
void setRGBA(QRgb rgb) { setRGBA(qRed(rgb), qGreen(rgb), qBlue(rgb), qAlpha(rgb)); }
|
||||
quint32 hermiteX;
|
||||
quint32 hermiteY;
|
||||
quint32 hermiteZ;
|
||||
|
||||
bool isSet() const { return rgba[3] != 0; }
|
||||
Entry();
|
||||
|
||||
bool isSet() const { return qAlpha(color) != 0; }
|
||||
|
||||
bool isZero() const;
|
||||
bool isMergeable(const Entry& other) const;
|
||||
|
||||
void setHermiteX(int x, int y, int z, int w) { hermiteX[0] = x; hermiteX[1] = y; hermiteX[2] = z; hermiteX[3] = w; }
|
||||
void setHermiteX(const glm::vec3& normal, float position);
|
||||
void clearHermiteX() { setHermiteX(0, 0, 0, 0); }
|
||||
float getHermiteX(glm::vec3& normal) 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); }
|
||||
float getHermiteY(glm::vec3& normal) const;
|
||||
|
||||
void setHermiteZ(int x, int y, int z, int w) { hermiteZ[0] = x; hermiteZ[1] = y; hermiteZ[2] = z; hermiteZ[3] = w; }
|
||||
void setHermiteZ(const glm::vec3& normal, float position);
|
||||
void clearHermiteZ() { setHermiteZ(0, 0, 0, 0); }
|
||||
float getHermiteZ(glm::vec3& normal) const;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
|
@ -529,6 +520,9 @@ public:
|
|||
|
||||
int getEntryAlpha(int y) const;
|
||||
|
||||
Entry& getEntry(int y);
|
||||
const Entry& getEntry(int y) const;
|
||||
|
||||
void removeEntries(int position, int count) { remove(sizeof(quint16) + position * sizeof(Entry), count * sizeof(Entry)); }
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue