mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 12:04:18 +02:00
More rendering bits.
This commit is contained in:
parent
83967d49cf
commit
08dfd28ec0
2 changed files with 129 additions and 84 deletions
|
@ -1338,9 +1338,20 @@ class NormalIndex {
|
|||
public:
|
||||
int indices[MAX_NORMALS_PER_VERTEX];
|
||||
|
||||
bool isValid() const;
|
||||
|
||||
int getClosestIndex(const glm::vec3& normal, QVector<VoxelPoint>& vertices) const;
|
||||
};
|
||||
|
||||
bool NormalIndex::isValid() const {
|
||||
for (int i = 0; i < MAX_NORMALS_PER_VERTEX; i++) {
|
||||
if (indices[i] != 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int NormalIndex::getClosestIndex(const glm::vec3& normal, QVector<VoxelPoint>& vertices) const {
|
||||
int firstIndex = indices[0];
|
||||
int closestIndex = firstIndex;
|
||||
|
@ -2157,6 +2168,22 @@ HeightfieldNodeRenderer::~HeightfieldNodeRenderer() {
|
|||
Q_ARG(int, _colorTextureID), Q_ARG(int, _materialTextureID));
|
||||
}
|
||||
|
||||
class IndexVector : public QVector<NormalIndex> {
|
||||
public:
|
||||
|
||||
int position;
|
||||
|
||||
void swap(IndexVector& other) { QVector<NormalIndex>::swap(other); qSwap(position, other.position); }
|
||||
|
||||
const NormalIndex& get(int y) const;
|
||||
};
|
||||
|
||||
const NormalIndex& IndexVector::get(int y) const {
|
||||
static NormalIndex nullIndex = { { 0, 0, 0, 0 } };
|
||||
int relative = y - position;
|
||||
return (relative >= 0 && relative < size()) ? at(relative) : nullIndex;
|
||||
}
|
||||
|
||||
void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||
const glm::quat& rotation, const glm::vec3& scale, bool cursor) {
|
||||
if (!node->getHeight()) {
|
||||
|
@ -2298,12 +2325,23 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
const int EDGES_PER_CUBE = 12;
|
||||
EdgeCrossing crossings[EDGES_PER_CUBE];
|
||||
|
||||
IndexVector indicesX;
|
||||
IndexVector lastIndicesX;
|
||||
QVector<IndexVector> indicesZ(stackWidth + 1);
|
||||
QVector<IndexVector> lastIndicesZ(stackWidth + 1);
|
||||
|
||||
for (int z = 0; z <= stackHeight; z++) {
|
||||
const StackArray* lineSrc = src;
|
||||
for (int x = 0; x <= stackWidth; x++) {
|
||||
if (!lineSrc->isEmpty()) {
|
||||
int y = lineSrc->getPosition();
|
||||
int position = lineSrc->getPosition();
|
||||
int count = lineSrc->getEntryCount();
|
||||
int y = position;
|
||||
NormalIndex lastIndexY;
|
||||
indicesX.position = position;
|
||||
indicesX.resize(count);
|
||||
indicesZ[x].position = position;
|
||||
indicesZ[x].resize(count);
|
||||
for (const StackArray::Entry* entry = lineSrc->getEntryData(), *end = entry + lineSrc->getEntryCount();
|
||||
entry != end; entry++, y++) {
|
||||
int clampedX = qMax(x - 1, 0), clampedZ = qMax(z - 1, 0);
|
||||
|
@ -2579,29 +2617,118 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
// the first x, y, and z are repeated for the boundary edge; past that, we consider generating
|
||||
// quads for each edge that includes a transition, using indices of previously generated vertices
|
||||
if (x != 0 && z != 0) {
|
||||
int reclampedX = qMin(clampedX, stackWidth - 1);
|
||||
int reclampedZ = qMin(clampedZ, stackHeight - 1);
|
||||
if (alpha0 != alpha1) {
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size());
|
||||
if (y > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ), indices.size());
|
||||
}
|
||||
if (reclampedZ > 0) {
|
||||
if (y > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ - 1), indices.size());
|
||||
}
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size());
|
||||
}
|
||||
|
||||
const NormalIndex& index1 = lastIndexY;
|
||||
const NormalIndex& index2 = lastIndicesZ[x].get(y - 1);
|
||||
const NormalIndex& index3 = lastIndicesZ[x].get(y);
|
||||
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,
|
||||
vertices.at(index3.indices[0]).vertex - first);
|
||||
|
||||
if (alpha0 == 0) { // quad faces negative x
|
||||
indices.append(index3.getClosestIndex(normal = -normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
} else { // quad faces positive x
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index3.getClosestIndex(normal, vertices));
|
||||
}
|
||||
indices.append(index.getClosestIndex(normal, vertices));
|
||||
}
|
||||
|
||||
if (alpha0 != alpha2) {
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size());
|
||||
if (reclampedX > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ), indices.size());
|
||||
if (reclampedZ > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ - 1), indices.size());
|
||||
}
|
||||
}
|
||||
if (reclampedZ > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ - 1), indices.size());
|
||||
}
|
||||
|
||||
const NormalIndex& index1 = lastIndicesZ[x].get(y);
|
||||
const NormalIndex& index2 = lastIndicesZ[x - 1].get(y);
|
||||
const NormalIndex& index3 = lastIndicesX.get(y);
|
||||
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index3.indices[0]).vertex - first,
|
||||
vertices.at(index1.indices[0]).vertex - first);
|
||||
|
||||
if (alpha0 == 0) { // quad faces negative y
|
||||
indices.append(index1.getClosestIndex(normal = -normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index3.getClosestIndex(normal, vertices));
|
||||
} else { // quad faces positive y
|
||||
indices.append(index3.getClosestIndex(normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
}
|
||||
indices.append(index.getClosestIndex(normal, vertices));
|
||||
}
|
||||
|
||||
if (alpha0 != alpha4) {
|
||||
quadIndices.insert(qRgb(reclampedX, y, reclampedZ), indices.size());
|
||||
if (reclampedX > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX - 1, y, reclampedZ), indices.size());
|
||||
if (y > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX - 1, y - 1, reclampedZ), indices.size());
|
||||
}
|
||||
}
|
||||
if (y > 0) {
|
||||
quadIndices.insert(qRgb(reclampedX, y - 1, reclampedZ), indices.size());
|
||||
}
|
||||
|
||||
const NormalIndex& index1 = lastIndexY;
|
||||
const NormalIndex& index2 = lastIndicesX.get(y - 1);
|
||||
const NormalIndex& index3 = lastIndicesX.get(y);
|
||||
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(vertices.at(index1.indices[0]).vertex - first,
|
||||
vertices.at(index3.indices[0]).vertex - first);
|
||||
|
||||
if (alpha0 == 0) { // quad faces negative z
|
||||
indices.append(index3.getClosestIndex(normal = -normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
} else { // quad faces positive z
|
||||
indices.append(index1.getClosestIndex(normal, vertices));
|
||||
indices.append(index2.getClosestIndex(normal, vertices));
|
||||
indices.append(index3.getClosestIndex(normal, vertices));
|
||||
}
|
||||
indices.append(index.getClosestIndex(normal, vertices));
|
||||
}
|
||||
}
|
||||
|
||||
lastIndexY = index;
|
||||
indicesX[y - position] = index;
|
||||
indicesZ[x][y - position] = index;
|
||||
}
|
||||
}
|
||||
if (x != 0) {
|
||||
lineSrc++;
|
||||
}
|
||||
indicesX.swap(lastIndicesX);
|
||||
}
|
||||
if (z != 0) {
|
||||
src += stackWidth;
|
||||
}
|
||||
indicesZ.swap(lastIndicesZ);
|
||||
}
|
||||
|
||||
_voxels = new VoxelBuffer(vertices, indices, hermiteSegments, quadIndices, width, node->getStack()->getMaterials());
|
||||
|
|
|
@ -2226,7 +2226,6 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
float startZ = glm::clamp(start.z, 0.0f, (float)highestHeightZ), endZ = glm::clamp(end.z, 0.0f, (float)highestHeightZ);
|
||||
glm::vec3 worldStart = glm::vec3(transform * glm::vec4(startX, start.y, startZ, 1.0f));
|
||||
glm::vec3 worldStepX = glm::vec3(transform * glm::vec4(stepX, 0.0f, 0.0f, 0.0f));
|
||||
glm::vec3 worldStepY = glm::vec3(transform * glm::vec4(0.0f, start.y - end.y, 0.0f, 0.0f));
|
||||
glm::vec3 worldStepZ = glm::vec3(transform * glm::vec4(0.0f, 0.0f, stepZ, 0.0f));
|
||||
float voxelStep = scale.x / innerHeightWidth;
|
||||
float voxelScale = scale.y / (numeric_limits<quint16>::max() * voxelStep);
|
||||
|
@ -2237,7 +2236,6 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
int newBottom = end.y * voxelScale;
|
||||
QRgb rgba = color.rgba();
|
||||
bool erase = (color.alpha() == 0);
|
||||
uchar materialMaterialIndex = getMaterialIndex(material, newMaterialMaterials, newMaterialContents);
|
||||
QByteArray dummyContents;
|
||||
uchar stackMaterialIndex = getMaterialIndex(material, newStackMaterials, dummyContents);
|
||||
bool hasOwnColors = spanner->hasOwnColors();
|
||||
|
@ -2248,7 +2246,6 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
glm::vec3 worldPos = worldStart;
|
||||
for (float x = startX; x >= endX; x -= stepX, worldPos -= worldStepX) {
|
||||
quint16* heightLineDest = heightDest + (int)x;
|
||||
glm::vec3 endPos = worldPos - worldStepY;
|
||||
float distance;
|
||||
glm::vec3 normal;
|
||||
|
||||
|
@ -2266,10 +2263,6 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
float stackX = (x - HeightfieldHeight::HEIGHT_BORDER) * innerStackWidth / innerHeightWidth;
|
||||
float stackZ = (z - HeightfieldHeight::HEIGHT_BORDER) * innerStackHeight / innerHeightHeight;
|
||||
|
||||
int topHeight = -1;
|
||||
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;
|
||||
if (stackDest->isEmpty() && *heightLineDest != 0) {
|
||||
|
@ -2423,24 +2416,9 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
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) +
|
||||
qAlpha(topEntry->hermiteY) / (float)numeric_limits<quint8>::max()) / voxelScale;
|
||||
topColor = topEntry->color;
|
||||
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(
|
||||
|
@ -2451,66 +2429,6 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
|
|||
stackDest->getPositionRef() += beginningPruneCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (topHeight != -1) {
|
||||
*heightLineDest = topHeight;
|
||||
if (colorDest) {
|
||||
colorDest[0] = qRed(topColor);
|
||||
colorDest[1] = qGreen(topColor);
|
||||
colorDest[2] = qBlue(topColor);
|
||||
}
|
||||
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) {
|
||||
*heightLineDest = height;
|
||||
}
|
||||
}
|
||||
} else if (spanner->intersects(worldPos, endPos, distance, normal)) {
|
||||
quint16 height = glm::round(glm::mix(start.y, end.y, distance));
|
||||
if (height >= *heightLineDest) {
|
||||
*heightLineDest = height;
|
||||
|
||||
if (colorDest) {
|
||||
if (hasOwnColors) {
|
||||
QRgb spannerColor = spanner->getColorAt(glm::mix(endPos, worldPos, distance));
|
||||
colorDest[0] = qRed(spannerColor);
|
||||
colorDest[1] = qGreen(spannerColor);
|
||||
colorDest[2] = qBlue(spannerColor);
|
||||
|
||||
} else {
|
||||
colorDest[0] = color.red();
|
||||
colorDest[1] = color.green();
|
||||
colorDest[2] = color.blue();
|
||||
}
|
||||
}
|
||||
|
||||
if (materialDest) {
|
||||
if (hasOwnMaterials) {
|
||||
int index = spanner->getMaterialAt(glm::mix(endPos, worldPos, distance));
|
||||
if (index != 0) {
|
||||
int& mapping = materialMappings[index];
|
||||
if (mapping == 0) {
|
||||
mapping = getMaterialIndex(spanner->getMaterials().at(index - 1),
|
||||
newMaterialMaterials, newMaterialContents);
|
||||
}
|
||||
index = mapping;
|
||||
}
|
||||
*materialDest = index;
|
||||
|
||||
} else {
|
||||
*materialDest = materialMaterialIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
clearUnusedMaterials(newMaterialMaterials, newMaterialContents);
|
||||
|
|
Loading…
Reference in a new issue