mirror of
https://github.com/overte-org/overte.git
synced 2025-04-15 12:28:51 +02:00
Merge pull request #4142 from ey6es/master
Fix for color/material texture alignment.
This commit is contained in:
commit
b8f97ca978
3 changed files with 214 additions and 319 deletions
|
@ -43,5 +43,5 @@ void main(void) {
|
|||
gl_FrontColor = vec4(1.0, 1.0, 1.0, step(height, 0.0));
|
||||
|
||||
// pass along the scaled/offset texture coordinates
|
||||
gl_TexCoord[0] = vec4((heightCoord - heightScale.st) * colorScale, 0.0, 1.0);
|
||||
gl_TexCoord[0] = vec4((heightCoord - vec2(0.5, 0.5)) * colorScale + vec2(0.5, 0.5), 0.0, 1.0);
|
||||
}
|
||||
|
|
|
@ -58,7 +58,7 @@ void main(void) {
|
|||
gl_TexCoord[3] = textureSpacePosition * vec4(splatTextureScalesS[3], splatTextureScalesT[3], 0.0, 1.0);
|
||||
|
||||
// compute the alpha values for each texture
|
||||
float value = texture2D(textureMap, (gl_MultiTexCoord0.st - heightScale) * textureScale).r;
|
||||
float value = texture2D(textureMap, (gl_MultiTexCoord0.st - vec2(0.5, 0.5)) * textureScale + vec2(0.5, 0.5)).r;
|
||||
vec4 valueVector = vec4(value, value, value, value);
|
||||
alphaValues = step(textureValueMinima, valueVector) * step(valueVector, textureValueMaxima);
|
||||
}
|
||||
|
|
|
@ -1425,8 +1425,18 @@ public:
|
|||
char material;
|
||||
|
||||
void setColorMaterial(const StackArray::Entry& entry) { color = entry.color; material = entry.material; }
|
||||
|
||||
void mix(const EdgeCrossing& first, const EdgeCrossing& second, float t);
|
||||
};
|
||||
|
||||
void EdgeCrossing::mix(const EdgeCrossing& first, const EdgeCrossing& second, float t) {
|
||||
point = glm::mix(first.point, second.point, t);
|
||||
normal = glm::normalize(glm::mix(first.normal, second.normal, t));
|
||||
color = qRgb(glm::mix(qRed(first.color), qRed(second.color), t), glm::mix(qGreen(first.color), qGreen(second.color), t),
|
||||
glm::mix(qBlue(first.color), qBlue(second.color), t));
|
||||
material = (t < 0.5f) ? first.material : second.material;
|
||||
}
|
||||
|
||||
const int MAX_NORMALS_PER_VERTEX = 4;
|
||||
|
||||
class NormalIndex {
|
||||
|
@ -1480,7 +1490,6 @@ public:
|
|||
void swap(IndexVector& other) { QVector<NormalIndex>::swap(other); qSwap(position, other.position); }
|
||||
|
||||
const NormalIndex& get(int y) const;
|
||||
const NormalIndex& getClosest(int y) const;
|
||||
};
|
||||
|
||||
const NormalIndex& IndexVector::get(int y) const {
|
||||
|
@ -1489,56 +1498,6 @@ const NormalIndex& IndexVector::get(int y) const {
|
|||
return (relative >= 0 && relative < size()) ? at(relative) : invalidIndex;
|
||||
}
|
||||
|
||||
const NormalIndex& IndexVector::getClosest(int y) const {
|
||||
static NormalIndex invalidIndex = { { -1, -1, -1, -1 } };
|
||||
int relative = y - position;
|
||||
if (relative < 0 || relative >= size()) {
|
||||
return invalidIndex;
|
||||
}
|
||||
const NormalIndex& first = at(relative);
|
||||
if (first.isValid()) {
|
||||
return first;
|
||||
}
|
||||
for (int distance = 1; relative - distance >= 0 || relative + distance < size(); distance++) {
|
||||
int previous = relative - distance;
|
||||
if (previous >= 0) {
|
||||
const NormalIndex& previousIndex = at(previous);
|
||||
if (previousIndex.isValid()) {
|
||||
return previousIndex;
|
||||
}
|
||||
}
|
||||
int next = relative + distance;
|
||||
if (next < size()) {
|
||||
const NormalIndex& nextIndex = at(next);
|
||||
if (nextIndex.isValid()) {
|
||||
return nextIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
return invalidIndex;
|
||||
}
|
||||
|
||||
static inline void appendIndices(QVector<int>& indices, QMultiHash<VoxelCoord, int>& quadIndices,
|
||||
const QVector<VoxelPoint>& vertices, float step, int i0, int i1, int i2, int i3) {
|
||||
int newIndices[] = { i0, i1, i2, i3 };
|
||||
glm::vec3 minima(FLT_MAX, FLT_MAX, FLT_MAX), maxima(-FLT_MAX, -FLT_MAX, -FLT_MAX);
|
||||
int indexIndex = indices.size();
|
||||
for (unsigned int i = 0; i < sizeof(newIndices) / sizeof(newIndices[0]); i++) {
|
||||
int index = newIndices[i];
|
||||
indices.append(index);
|
||||
const glm::vec3& vertex = vertices.at(index).vertex;
|
||||
minima = glm::min(vertex, minima);
|
||||
maxima = glm::max(vertex, maxima);
|
||||
}
|
||||
for (int z = (int)minima.z, endZ = (int)glm::ceil(maxima.z); z < endZ; z++) {
|
||||
for (int y = (int)minima.x, endY = (int)glm::ceil(maxima.y); y < endY; y++) {
|
||||
for (int x = (int)minima.x, endX = (int)glm::ceil(maxima.x); x < endX; x++) {
|
||||
quadIndices.insert(qRgb(x, y, z), indexIndex);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const glm::vec3& translation,
|
||||
const glm::quat& rotation, const glm::vec3& scale, bool cursor) {
|
||||
if (!node->getHeight()) {
|
||||
|
@ -1617,7 +1576,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
|
||||
glGenTextures(1, &_colorTextureID);
|
||||
glBindTexture(GL_TEXTURE_2D, _colorTextureID);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
|
||||
if (node->getColor()) {
|
||||
|
@ -1625,6 +1584,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB8, node->getColor()->getWidth(),
|
||||
contents.size() / (node->getColor()->getWidth() * DataBlock::COLOR_BYTES),
|
||||
0, GL_RGB, GL_UNSIGNED_BYTE, contents.constData());
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
|
||||
} else {
|
||||
const quint8 WHITE_COLOR[] = { 255, 255, 255 };
|
||||
|
@ -1705,7 +1665,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
}
|
||||
|
||||
const int EDGES_PER_CUBE = 12;
|
||||
EdgeCrossing crossings[EDGES_PER_CUBE];
|
||||
EdgeCrossing crossings[EDGES_PER_CUBE * 2];
|
||||
|
||||
// as we scan down the cube generating vertices between grid points, we remember the indices of the last
|
||||
// (element, line, section--x, y, z) so that we can connect generated vertices as quads
|
||||
|
@ -1736,13 +1696,6 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
lineSrc[stackWidth].getExtents(minimumY, maximumY);
|
||||
}
|
||||
if (maximumY >= minimumY) {
|
||||
int position = minimumY;
|
||||
int count = maximumY - minimumY + 1;
|
||||
NormalIndex lastIndexY = { { -1, -1, -1, -1 } };
|
||||
indicesX.position = position;
|
||||
indicesX.resize(count);
|
||||
indicesZ[x].position = position;
|
||||
indicesZ[x].resize(count);
|
||||
float heightfieldHeight = *heightLineSrc * voxelScale;
|
||||
float nextHeightfieldHeightX = heightLineSrc[1] * voxelScale;
|
||||
float nextHeightfieldHeightZ = heightLineSrc[width] * voxelScale;
|
||||
|
@ -1753,6 +1706,8 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
const int LOWER_RIGHT_CORNER = 8;
|
||||
const int NO_CORNERS = 0;
|
||||
const int ALL_CORNERS = UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER | LOWER_RIGHT_CORNER;
|
||||
const int CORNER_COUNT = 4;
|
||||
const int NEXT_CORNERS[] = { 1, 3, 0, 2 };
|
||||
int corners = NO_CORNERS;
|
||||
if (heightfieldHeight != 0.0f) {
|
||||
corners |= UPPER_LEFT_CORNER;
|
||||
|
@ -1767,37 +1722,38 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
corners |= LOWER_RIGHT_CORNER;
|
||||
}
|
||||
bool stitchable = x != 0 && z != 0 && !(corners == NO_CORNERS || corners == ALL_CORNERS);
|
||||
VoxelPoint cornerPoints[4];
|
||||
EdgeCrossing cornerCrossings[CORNER_COUNT];
|
||||
int clampedX = qMax(x - 1, 0), clampedZ = qMax(z - 1, 0);
|
||||
int cornerMinimumY = INT_MAX, cornerMaximumY = -1;
|
||||
if (stitchable) {
|
||||
for (unsigned int i = 0; i < sizeof(cornerPoints) / sizeof(cornerPoints[0]); i++) {
|
||||
for (int i = 0; i < CORNER_COUNT; i++) {
|
||||
if (!(corners & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* height = heightLineSrc + offsetZ * width + offsetX;
|
||||
VoxelPoint& point = cornerPoints[i];
|
||||
int clampedOffsetX = clampedX + offsetX, clampedOffsetZ = clampedZ + offsetZ;
|
||||
point.vertex = glm::vec3(clampedOffsetX, *height * voxelScale, clampedOffsetZ) * step;
|
||||
float heightValue = *height * voxelScale;
|
||||
int y = (int)heightValue;
|
||||
cornerMinimumY = qMin(cornerMinimumY, y);
|
||||
cornerMaximumY = qMax(cornerMaximumY, y);
|
||||
EdgeCrossing& crossing = cornerCrossings[i];
|
||||
crossing.point = glm::vec3(offsetX, heightValue, offsetZ);
|
||||
int left = height[-1];
|
||||
int right = height[1];
|
||||
int down = height[-width];
|
||||
int up = height[width];
|
||||
glm::vec3 normal = glm::normalize(glm::vec3((left == 0 || right == 0) ? 0.0f : left - right,
|
||||
crossing.normal = glm::normalize(glm::vec3((left == 0 || right == 0) ? 0.0f : left - right,
|
||||
2.0f / voxelScale, (up == 0 || down == 0) ? 0.0f : down - up));
|
||||
point.normal[0] = normal.x * numeric_limits<qint8>::max();
|
||||
point.normal[1] = normal.y * numeric_limits<qint8>::max();
|
||||
point.normal[2] = normal.z * numeric_limits<qint8>::max();
|
||||
int clampedOffsetX = clampedX + offsetX, clampedOffsetZ = clampedZ + offsetZ;
|
||||
if (colorSrc) {
|
||||
const uchar* color = colorSrc + ((int)(clampedOffsetZ * colorStepZ) * colorWidth +
|
||||
(int)(clampedOffsetX * colorStepX)) * DataBlock::COLOR_BYTES;
|
||||
point.color[0] = color[0];
|
||||
point.color[1] = color[1];
|
||||
point.color[2] = color[2];
|
||||
|
||||
crossing.color = qRgb(color[0], color[1], color[2]);
|
||||
|
||||
} else {
|
||||
point.color[0] = point.color[1] = point.color[2] = numeric_limits<quint8>::max();
|
||||
crossing.color = qRgb(numeric_limits<quint8>::max(), numeric_limits<quint8>::max(),
|
||||
numeric_limits<quint8>::max());
|
||||
}
|
||||
int material = 0;
|
||||
if (materialSrc) {
|
||||
|
@ -1812,12 +1768,18 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
material = mapping;
|
||||
}
|
||||
}
|
||||
point.materials[0] = material;
|
||||
point.materials[1] = point.materials[2] = point.materials[3] = 0;
|
||||
point.materialWeights[0] = numeric_limits<quint8>::max();
|
||||
point.materialWeights[1] = point.materialWeights[2] = point.materialWeights[3] = 0;
|
||||
crossing.material = material;
|
||||
}
|
||||
minimumY = qMin(minimumY, cornerMinimumY);
|
||||
maximumY = qMax(maximumY, cornerMaximumY);
|
||||
}
|
||||
int position = minimumY;
|
||||
int count = maximumY - minimumY + 1;
|
||||
NormalIndex lastIndexY = { { -1, -1, -1, -1 } };
|
||||
indicesX.position = position;
|
||||
indicesX.resize(count);
|
||||
indicesZ[x].position = position;
|
||||
indicesZ[x].resize(count);
|
||||
for (int y = position, end = position + count; y < end; y++) {
|
||||
const StackArray::Entry& entry = lineSrc->getEntry(y, heightfieldHeight);
|
||||
if (displayHermite && x != 0 && z != 0 && !lineSrc->isEmpty() && y >= lineSrc->getPosition()) {
|
||||
|
@ -1875,91 +1837,179 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
if (alphaTotal == 0 || alphaTotal == possibleTotal) {
|
||||
continue; // no corners set/all corners set
|
||||
}
|
||||
// we first look for crossings with the heightfield corner vertices; these take priority
|
||||
int crossingCount = 0;
|
||||
if (y >= cornerMinimumY && y <= cornerMaximumY) {
|
||||
// first look for set corners, which override any interpolated values
|
||||
int crossedCorners = NO_CORNERS;
|
||||
for (int i = 0; i < CORNER_COUNT; i++) {
|
||||
if (!(corners & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* height = heightLineSrc + offsetZ * width + offsetX;
|
||||
float heightValue = *height * voxelScale;
|
||||
if (heightValue >= y && heightValue < y + 1) {
|
||||
crossedCorners |= (1 << i);
|
||||
}
|
||||
}
|
||||
switch (crossedCorners) {
|
||||
case UPPER_LEFT_CORNER:
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER:
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER:
|
||||
case UPPER_LEFT_CORNER | LOWER_RIGHT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[0];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
case UPPER_RIGHT_CORNER:
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER:
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[1];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
case LOWER_LEFT_CORNER:
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER | UPPER_LEFT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[2];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
case LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER:
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER:
|
||||
crossings[crossingCount++] = cornerCrossings[3];
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
break;
|
||||
|
||||
case NO_CORNERS:
|
||||
for (int i = 0; i < CORNER_COUNT; i++) {
|
||||
if (!(corners & (1 << i))) {
|
||||
continue;
|
||||
}
|
||||
int offsetX = (i & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int offsetZ = (i & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* height = heightLineSrc + offsetZ * width + offsetX;
|
||||
float heightValue = *height * voxelScale;
|
||||
int nextIndex = NEXT_CORNERS[i];
|
||||
if (!(corners & (1 << nextIndex))) {
|
||||
continue;
|
||||
}
|
||||
int nextOffsetX = (nextIndex & X_MAXIMUM_FLAG) ? 1 : 0;
|
||||
int nextOffsetZ = (nextIndex & Y_MAXIMUM_FLAG) ? 1 : 0;
|
||||
const quint16* nextHeight = heightLineSrc + nextOffsetZ * width + nextOffsetX;
|
||||
float nextHeightValue = *nextHeight * voxelScale;
|
||||
float divisor = (nextHeightValue - heightValue);
|
||||
if (divisor == 0.0f) {
|
||||
continue;
|
||||
}
|
||||
float t1 = (y - heightValue) / divisor;
|
||||
float t2 = (y + 1 - heightValue) / divisor;
|
||||
if (t1 >= 0.0f && t1 <= 1.0f) {
|
||||
crossings[crossingCount++].mix(cornerCrossings[i], cornerCrossings[nextIndex], t1);
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
}
|
||||
if (t2 >= 0.0f && t2 <= 1.0f) {
|
||||
crossings[crossingCount++].mix(cornerCrossings[i], cornerCrossings[nextIndex], t2);
|
||||
crossings[crossingCount - 1].point.y -= y;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
const StackArray::Entry& nextEntryY = lineSrc->getEntry(y + 1, heightfieldHeight);
|
||||
if (middleX) {
|
||||
const StackArray::Entry& nextEntryX = lineSrc[1].getEntry(y, nextHeightfieldHeightX);
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1, nextHeightfieldHeightX);
|
||||
if (alpha0 != alpha1) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(entry.getHermiteX(crossing.normal), 0.0f, 0.0f);
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryX : entry);
|
||||
if (crossingCount == 0) {
|
||||
const StackArray::Entry& nextEntryY = lineSrc->getEntry(y + 1, heightfieldHeight);
|
||||
if (middleX) {
|
||||
const StackArray::Entry& nextEntryX = lineSrc[1].getEntry(y, nextHeightfieldHeightX);
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1, nextHeightfieldHeightX);
|
||||
if (alpha0 != alpha1) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(entry.getHermiteX(crossing.normal), 0.0f, 0.0f);
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryX : entry);
|
||||
}
|
||||
if (alpha1 != alpha3) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(1.0f, nextEntryX.getHermiteY(crossing.normal), 0.0f);
|
||||
crossing.setColorMaterial(alpha1 == 0 ? nextEntryXY : nextEntryX);
|
||||
}
|
||||
if (alpha2 != alpha3) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(nextEntryY.getHermiteX(crossing.normal), 1.0f, 0.0f);
|
||||
crossing.setColorMaterial(alpha2 == 0 ? nextEntryXY : nextEntryY);
|
||||
}
|
||||
if (middleZ) {
|
||||
const StackArray::Entry& nextEntryZ = lineSrc[stackWidth].getEntry(y,
|
||||
nextHeightfieldHeightZ);
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
const StackArray::Entry& nextEntryXYZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y + 1, nextHeightfieldHeightXZ);
|
||||
if (alpha1 != alpha5) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(1.0f, 0.0f, nextEntryX.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha1 == 0 ? nextEntryXZ : nextEntryX);
|
||||
}
|
||||
if (alpha3 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1,
|
||||
nextHeightfieldHeightX);
|
||||
crossing.point = glm::vec3(1.0f, 1.0f, nextEntryXY.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha3 == 0 ? nextEntryXYZ : nextEntryXY);
|
||||
}
|
||||
if (alpha4 != alpha5) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(nextEntryZ.getHermiteX(crossing.normal), 0.0f, 1.0f);
|
||||
crossing.setColorMaterial(alpha4 == 0 ? nextEntryXZ : nextEntryZ);
|
||||
}
|
||||
if (alpha5 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
crossing.point = glm::vec3(1.0f, nextEntryXZ.getHermiteY(crossing.normal), 1.0f);
|
||||
crossing.setColorMaterial(alpha5 == 0 ? nextEntryXYZ : nextEntryXZ);
|
||||
}
|
||||
if (alpha6 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(
|
||||
y + 1, nextHeightfieldHeightZ);
|
||||
crossing.point = glm::vec3(nextEntryYZ.getHermiteX(crossing.normal), 1.0f, 1.0f);
|
||||
crossing.setColorMaterial(alpha6 == 0 ? nextEntryXYZ : nextEntryYZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alpha1 != alpha3) {
|
||||
if (alpha0 != alpha2) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(1.0f, nextEntryX.getHermiteY(crossing.normal), 0.0f);
|
||||
crossing.setColorMaterial(alpha1 == 0 ? nextEntryXY : nextEntryX);
|
||||
}
|
||||
if (alpha2 != alpha3) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(nextEntryY.getHermiteX(crossing.normal), 1.0f, 0.0f);
|
||||
crossing.setColorMaterial(alpha2 == 0 ? nextEntryXY : nextEntryY);
|
||||
crossing.point = glm::vec3(0.0f, entry.getHermiteY(crossing.normal), 0.0f);
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryY : entry);
|
||||
}
|
||||
if (middleZ) {
|
||||
const StackArray::Entry& nextEntryZ = lineSrc[stackWidth].getEntry(y, nextHeightfieldHeightZ);
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
const StackArray::Entry& nextEntryXYZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y + 1, nextHeightfieldHeightXZ);
|
||||
if (alpha1 != alpha5) {
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(y + 1,
|
||||
nextHeightfieldHeightZ);
|
||||
if (alpha0 != alpha4) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(1.0f, 0.0f, nextEntryX.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha1 == 0 ? nextEntryXZ : nextEntryX);
|
||||
crossing.point = glm::vec3(0.0f, 0.0f, entry.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryZ : entry);
|
||||
}
|
||||
if (alpha3 != alpha7) {
|
||||
if (alpha2 != alpha6) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXY = lineSrc[1].getEntry(y + 1, nextHeightfieldHeightX);
|
||||
crossing.point = glm::vec3(1.0f, 1.0f, nextEntryXY.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha3 == 0 ? nextEntryXYZ : nextEntryXY);
|
||||
crossing.point = glm::vec3(0.0f, 1.0f, nextEntryY.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha2 == 0 ? nextEntryYZ : nextEntryY);
|
||||
}
|
||||
if (alpha4 != alpha5) {
|
||||
if (alpha4 != alpha6) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(nextEntryZ.getHermiteX(crossing.normal), 0.0f, 1.0f);
|
||||
crossing.setColorMaterial(alpha4 == 0 ? nextEntryXZ : nextEntryZ);
|
||||
}
|
||||
if (alpha5 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryXZ = lineSrc[stackWidth + 1].getEntry(
|
||||
y, nextHeightfieldHeightXZ);
|
||||
crossing.point = glm::vec3(1.0f, nextEntryXZ.getHermiteY(crossing.normal), 1.0f);
|
||||
crossing.setColorMaterial(alpha5 == 0 ? nextEntryXYZ : nextEntryXZ);
|
||||
}
|
||||
if (alpha6 != alpha7) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(
|
||||
y + 1, nextHeightfieldHeightZ);
|
||||
crossing.point = glm::vec3(nextEntryYZ.getHermiteX(crossing.normal), 1.0f, 1.0f);
|
||||
crossing.setColorMaterial(alpha6 == 0 ? nextEntryXYZ : nextEntryYZ);
|
||||
crossing.point = glm::vec3(0.0f, nextEntryZ.getHermiteY(crossing.normal), 1.0f);
|
||||
crossing.setColorMaterial(alpha4 == 0 ? nextEntryYZ : nextEntryZ);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (alpha0 != alpha2) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(0.0f, entry.getHermiteY(crossing.normal), 0.0f);
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryY : entry);
|
||||
}
|
||||
if (middleZ) {
|
||||
const StackArray::Entry& nextEntryZ = lineSrc[stackWidth].getEntry(y, nextHeightfieldHeightZ);
|
||||
const StackArray::Entry& nextEntryYZ = lineSrc[stackWidth].getEntry(y + 1, nextHeightfieldHeightZ);
|
||||
if (alpha0 != alpha4) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(0.0f, 0.0f, entry.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha0 == 0 ? nextEntryZ : entry);
|
||||
}
|
||||
if (alpha2 != alpha6) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(0.0f, 1.0f, nextEntryY.getHermiteZ(crossing.normal));
|
||||
crossing.setColorMaterial(alpha2 == 0 ? nextEntryYZ : nextEntryY);
|
||||
}
|
||||
if (alpha4 != alpha6) {
|
||||
EdgeCrossing& crossing = crossings[crossingCount++];
|
||||
crossing.point = glm::vec3(0.0f, nextEntryZ.getHermiteY(crossing.normal), 1.0f);
|
||||
crossing.setColorMaterial(alpha4 == 0 ? nextEntryYZ : nextEntryZ);
|
||||
}
|
||||
}
|
||||
// determine whether we should ignore this vertex because it will be stitched
|
||||
// make sure we have valid crossings to include
|
||||
int validCrossings = 0;
|
||||
for (int i = 0; i < crossingCount; i++) {
|
||||
if (qAlpha(crossings[i].color) != 0) {
|
||||
|
@ -2107,173 +2157,6 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
point.setNormal(normals[i]);
|
||||
vertices.append(point);
|
||||
}
|
||||
|
||||
if (stitchable) {
|
||||
int nextIndex = vertices.size();
|
||||
const NormalIndex& previousIndexX = lastIndicesX.getClosest(y);
|
||||
const NormalIndex& previousIndexZ = lastIndicesZ[x].getClosest(y);
|
||||
switch (corners) {
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER: {
|
||||
vertices.append(cornerPoints[0]);
|
||||
vertices.append(cornerPoints[3]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[0].vertex - cornerPoints[1].vertex,
|
||||
cornerPoints[3].vertex - cornerPoints[1].vertex);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
nextIndex, previousIndexX.getClosestIndex(normal, vertices));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_LEFT_CORNER | LOWER_LEFT_CORNER | LOWER_RIGHT_CORNER: {
|
||||
vertices.append(cornerPoints[0]);
|
||||
vertices.append(cornerPoints[3]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[3].vertex - cornerPoints[2].vertex,
|
||||
cornerPoints[0].vertex - cornerPoints[2].vertex);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex, nextIndex + 1, nextIndex + 1);
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexZ.getClosestIndex(normal, vertices), nextIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[1]);
|
||||
vertices.append(cornerPoints[2]);
|
||||
vertices.append(cornerPoints[3]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[3].vertex - cornerPoints[2].vertex,
|
||||
cornerPoints[1].vertex - cornerPoints[2].vertex);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 2, nextIndex, nextIndex);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex + 2, nextIndex + 2);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexX.getClosestIndex(normal, vertices), nextIndex + 1);
|
||||
}
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
nextIndex, previousIndexZ.getClosestIndex(normal, vertices));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER | LOWER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[0]);
|
||||
vertices.append(cornerPoints[1]);
|
||||
vertices.append(cornerPoints[2]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[2].vertex - cornerPoints[0].vertex,
|
||||
cornerPoints[1].vertex - cornerPoints[0].vertex);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex, nextIndex + 2, nextIndex + 2);
|
||||
break;
|
||||
}
|
||||
case UPPER_LEFT_CORNER | UPPER_RIGHT_CORNER: {
|
||||
vertices.append(cornerPoints[0]);
|
||||
vertices.append(cornerPoints[1]);
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(cornerPoints[1].vertex - first,
|
||||
cornerPoints[0].vertex - first);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
nextIndex, previousIndexX.getClosestIndex(normal, vertices));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_RIGHT_CORNER | LOWER_RIGHT_CORNER: {
|
||||
vertices.append(cornerPoints[1]);
|
||||
vertices.append(cornerPoints[3]);
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(cornerPoints[3].vertex - first,
|
||||
cornerPoints[1].vertex - first);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
firstIndex, nextIndex, previousIndexZ.getClosestIndex(normal, vertices));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LOWER_RIGHT_CORNER | LOWER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[3]);
|
||||
vertices.append(cornerPoints[2]);
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(cornerPoints[2].vertex - first,
|
||||
cornerPoints[3].vertex - first);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexX.getClosestIndex(normal, vertices), nextIndex + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LOWER_LEFT_CORNER | UPPER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[2]);
|
||||
vertices.append(cornerPoints[0]);
|
||||
const glm::vec3& first = vertices.at(index.indices[0]).vertex;
|
||||
glm::vec3 normal = glm::cross(cornerPoints[0].vertex - first,
|
||||
cornerPoints[2].vertex - first);
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex,
|
||||
nextIndex + 1, nextIndex, nextIndex);
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexZ.getClosestIndex(normal, vertices), nextIndex + 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[0]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[0].vertex -
|
||||
vertices.at(index.indices[0]).vertex, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
nextIndex, previousIndexX.getClosestIndex(normal, vertices));
|
||||
}
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexZ.getClosestIndex(normal, vertices), nextIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UPPER_RIGHT_CORNER: {
|
||||
vertices.append(cornerPoints[1]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[1].vertex -
|
||||
vertices.at(index.indices[0]).vertex, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
if (previousIndexZ.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
nextIndex, previousIndexZ.getClosestIndex(normal, vertices));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case LOWER_LEFT_CORNER: {
|
||||
vertices.append(cornerPoints[2]);
|
||||
glm::vec3 normal = glm::cross(cornerPoints[2].vertex -
|
||||
vertices.at(index.indices[0]).vertex, glm::vec3(1.0f, 0.0f, 0.0f));
|
||||
int firstIndex = index.getClosestIndex(normal, vertices);
|
||||
if (previousIndexX.isValid()) {
|
||||
appendIndices(indices, quadIndices, vertices, step, firstIndex, firstIndex,
|
||||
previousIndexX.getClosestIndex(normal, vertices), nextIndex);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// the first x, y, and z are repeated for the boundary edge; past that, we consider generating
|
||||
|
@ -2407,7 +2290,14 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
baseBatch.heightTextureID = _heightTextureID;
|
||||
baseBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, (innerWidth - 1) / -2.0f, (innerHeight - 1) / -2.0f);
|
||||
baseBatch.colorTextureID = _colorTextureID;
|
||||
baseBatch.colorScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight);
|
||||
float widthMultiplier = 1.0f / (0.5f - 1.5f / width);
|
||||
float heightMultiplier = 1.0f / (0.5f - 1.5f / height);
|
||||
if (node->getColor()) {
|
||||
int colorWidth = node->getColor()->getWidth();
|
||||
int colorHeight = node->getColor()->getContents().size() / (colorWidth * DataBlock::COLOR_BYTES);
|
||||
baseBatch.colorScale = glm::vec2((0.5f - 0.5f / colorWidth) * widthMultiplier,
|
||||
(0.5f - 0.5f / colorHeight) * heightMultiplier);
|
||||
}
|
||||
Application::getInstance()->getMetavoxels()->addHeightfieldBaseBatch(baseBatch);
|
||||
|
||||
if (!(cursor || _networkTextures.isEmpty())) {
|
||||
|
@ -2422,7 +2312,12 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
|||
splatBatch.heightTextureID = _heightTextureID;
|
||||
splatBatch.heightScale = glm::vec4(1.0f / width, 1.0f / height, 0.0f, 0.0f);
|
||||
splatBatch.materialTextureID = _materialTextureID;
|
||||
splatBatch.textureScale = glm::vec2((float)width / innerWidth, (float)height / innerHeight);
|
||||
if (node->getMaterial()) {
|
||||
int materialWidth = node->getMaterial()->getWidth();
|
||||
int materialHeight = node->getMaterial()->getContents().size() / materialWidth;
|
||||
splatBatch.textureScale = glm::vec2((0.5f - 0.5f / materialWidth) * widthMultiplier,
|
||||
(0.5f - 0.5f / materialHeight) * heightMultiplier);
|
||||
}
|
||||
splatBatch.splatTextureOffset = glm::vec2(
|
||||
glm::dot(translation, rotation * glm::vec3(1.0f, 0.0f, 0.0f)) / scale.x,
|
||||
glm::dot(translation, rotation * glm::vec3(0.0f, 0.0f, 1.0f)) / scale.z);
|
||||
|
|
Loading…
Reference in a new issue