From de4776ef08b23887e2bd00b34b87c713666ff1d1 Mon Sep 17 00:00:00 2001 From: Andrzej Kapolka Date: Tue, 30 Dec 2014 15:36:22 -0800 Subject: [PATCH] More progress on rendering. --- interface/src/MetavoxelSystem.cpp | 72 +++++++++++++++++++- libraries/metavoxels/src/Spanner.cpp | 99 +++++++++++++++++----------- libraries/metavoxels/src/Spanner.h | 26 +++----- 3 files changed, 138 insertions(+), 59 deletions(-) diff --git a/interface/src/MetavoxelSystem.cpp b/interface/src/MetavoxelSystem.cpp index 84b91c80a1..d6b636f243 100644 --- a/interface/src/MetavoxelSystem.cpp +++ b/interface/src/MetavoxelSystem.cpp @@ -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::max(); @@ -2341,10 +2344,73 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g alphaTotal += (alpha6 = lineSrc[stackWidth].getEntryAlpha(y + 1)); possibleTotal += numeric_limits::max(); } - + int alpha5 = alpha4, alpha7 = alpha6; + if (middleX) { + alphaTotal += (alpha1 = lineSrc[1].getEntryAlpha(y)); + possibleTotal += numeric_limits::max(); + + alphaTotal += (alpha3 = lineSrc[1].getEntryAlpha(y + 1)); + possibleTotal += numeric_limits::max(); + + if (middleZ) { + alphaTotal += (alpha5 = lineSrc[stackWidth + 1].getEntryAlpha(y)); + possibleTotal += numeric_limits::max(); + + alphaTotal += (alpha7 = lineSrc[stackWidth + 1].getEntryAlpha(y + 1)); + possibleTotal += numeric_limits::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) { diff --git a/libraries/metavoxels/src/Spanner.cpp b/libraries/metavoxels/src/Spanner.cpp index 7abb41eedc..737a1189e8 100644 --- a/libraries/metavoxels/src/Spanner.cpp +++ b/libraries/metavoxels/src/Spanner.cpp @@ -1153,31 +1153,32 @@ static QVector 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::max(); - values[1] = normal.y * numeric_limits::max(); - values[2] = normal.z * numeric_limits::max(); - values[3] = position * numeric_limits::max(); +static inline void setHermite(quint32& value, const glm::vec3& normal, float position) { + value = qRgba(normal.x * numeric_limits::max(), normal.y * numeric_limits::max(), + normal.z * numeric_limits::max(), position * numeric_limits::max()); } -static inline float getHermite(const uchar values[4], glm::vec3& normal) { - normal.x = (char)values[0] / (float)numeric_limits::max(); - normal.y = (char)values[1] / (float)numeric_limits::max(); - normal.z = (char)values[2] / (float)numeric_limits::max(); - return values[3] / (float)numeric_limits::max(); +static inline float getHermite(QRgb value, glm::vec3& normal) { + normal.x = (char)qRed(value) / (float)numeric_limits::max(); + normal.y = (char)qGreen(value) / (float)numeric_limits::max(); + normal.z = (char)qBlue(value) / (float)numeric_limits::max(); + return qAlpha(value) / (float)numeric_limits::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& 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::max(); + oldDistance = qAlpha(entryDest->hermiteX) / (float)numeric_limits::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::max(); + oldDistance = qAlpha(entryDest->hermiteY) / (float)numeric_limits::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::max(); + oldDistance = qAlpha(entryDest->hermiteZ) / (float)numeric_limits::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::max()) / voxelScale; - topR = topEntry->rgba[0]; - topG = topEntry->rgba[1]; - topB = topEntry->rgba[2]; + qAlpha(topEntry->hermiteY) / (float)numeric_limits::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(); } } diff --git a/libraries/metavoxels/src/Spanner.h b/libraries/metavoxels/src/Spanner.h index 5028659609..a12c677b83 100644 --- a/libraries/metavoxels/src/Spanner.h +++ b/libraries/metavoxels/src/Spanner.h @@ -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)); } };