CSG improvements.

This commit is contained in:
Andrzej Kapolka 2015-01-08 12:52:52 -08:00
parent 4c3163fae8
commit ec32739689
2 changed files with 25 additions and 27 deletions

View file

@ -1857,30 +1857,22 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
} }
} }
// fall into four cases based on set corners // fall into four cases based on set corners
glm::vec3 center;
int offsetX = 0, offsetZ = 0; int offsetX = 0, offsetZ = 0;
switch(corners) { switch(corners) {
case 3: case 3:
case 11: // z- edge, x+/z- corner case 11: // z- edge, x+/z- corner
center = glm::vec3(1.0f, nextHeightfieldHeightX, 0.0f);
offsetX = 1; offsetX = 1;
break; break;
case 12: case 12:
case 13: // z+ edge, x-/z+ corner case 13: // z+ edge, x-/z+ corner
center = glm::vec3(0.0f, nextHeightfieldHeightZ, 1.0f);
offsetZ = 1; offsetZ = 1;
break; break;
case 10: case 10:
case 14: // x+ edge, x+/z+ corner case 14: // x+ edge, x+/z+ corner
center = glm::vec3(1.0f, nextHeightfieldHeightXZ, 1.0f);
offsetX = offsetZ = 1; offsetX = offsetZ = 1;
break; break;
default: // x- edge, x-/z- corner
center = glm::vec3(0.0f, heightfieldHeight, 0.0f);
break;
} }
const quint16* height = heightLineSrc + width * offsetZ + offsetX; const quint16* height = heightLineSrc + width * offsetZ + offsetX;
int left = height[-1]; int left = height[-1];

View file

@ -2209,9 +2209,9 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
stackDest->setPosition(newBottom); stackDest->setPosition(newBottom);
prepend = stackDest->getEntryCount(); prepend = stackDest->getEntryCount();
} }
const quint16* oldHeightLineDest = _height->getContents().constData() + (int)z * heightWidth + (int)x;
if (*heightLineDest != 0) { if (*heightLineDest != 0) {
float voxelHeight = *heightLineDest * voxelScale; float voxelHeight = *heightLineDest * voxelScale;
const quint16* oldHeightLineDest = _height->getContents().constData() + (int)z * heightWidth + (int)x;
float left = oldHeightLineDest[-1] * voxelScale; float left = oldHeightLineDest[-1] * voxelScale;
float right = oldHeightLineDest[1] * voxelScale; float right = oldHeightLineDest[1] * voxelScale;
float down = oldHeightLineDest[-heightWidth] * voxelScale; float down = oldHeightLineDest[-heightWidth] * voxelScale;
@ -2264,8 +2264,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
} }
StackArray::Entry* entryDest = stackDest->getEntryData() + (newTop - stackDest->getPosition()); StackArray::Entry* entryDest = stackDest->getEntryData() + (newTop - stackDest->getPosition());
glm::vec3 pos = worldPos; glm::vec3 pos = worldPos;
float voxelHeight = *heightLineDest * voxelScale;
float nextVoxelHeightX = heightLineDest[1] * voxelScale;
float nextVoxelHeightZ = heightLineDest[heightWidth] * voxelScale;
float oldVoxelHeight = *oldHeightLineDest * voxelScale;
float oldNextVoxelHeightX = oldHeightLineDest[1] * voxelScale;
float oldNextVoxelHeightZ = oldHeightLineDest[heightWidth] * voxelScale;
for (int y = newTop; y >= newBottom; y--, entryDest--, pos -= worldStepY) { for (int y = newTop; y >= newBottom; y--, entryDest--, pos -= worldStepY) {
bool oldCurrentSet = entryDest->isSet(); int oldCurrentAlpha = stackDest->getEntryAlpha(y, oldVoxelHeight);
if (spanner->contains(pos)) { if (spanner->contains(pos)) {
if (hasOwnColors && !erase) { if (hasOwnColors && !erase) {
entryDest->color = spanner->getColorAt(pos); entryDest->color = spanner->getColorAt(pos);
@ -2289,18 +2295,20 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
entryDest->material = stackMaterialIndex; entryDest->material = stackMaterialIndex;
} }
} }
bool currentSet = entryDest->isSet();
int currentAlpha = stackDest->getEntryAlpha(y, voxelHeight);
bool flipped = (color.alpha() == currentAlpha);
int nextStackX = (int)stackX + 1; int nextStackX = (int)stackX + 1;
if (nextStackX <= innerStackWidth) { if (nextStackX <= innerStackWidth) {
bool nextSetX = isSet(newStackContents, stackWidth, nextStackX, y, (int)stackZ); int nextAlphaX = newStackContents.at((int)stackZ * stackWidth + nextStackX).getEntryAlpha(
if (nextSetX == currentSet) { y, nextVoxelHeightX);
if (nextAlphaX == currentAlpha) {
entryDest->hermiteX = 0; entryDest->hermiteX = 0;
} else { } else {
bool flipped = (erase == nextSetX);
float oldDistance = flipped ? 0.0f : 1.0f; float oldDistance = flipped ? 0.0f : 1.0f;
if (currentSet == oldCurrentSet && nextSetX == isSet(oldStackContents, stackWidth, if (currentAlpha == oldCurrentAlpha && nextAlphaX == oldStackContents.at((int)stackZ * stackWidth +
nextStackX, y, (int)stackZ)) { nextStackX).getEntryAlpha(y, oldNextVoxelHeightX) && entryDest->hermiteX != 0) {
oldDistance = qAlpha(entryDest->hermiteX) / (float)numeric_limits<quint8>::max(); oldDistance = qAlpha(entryDest->hermiteX) / (float)numeric_limits<quint8>::max();
} }
if (flipped ? (spanner->intersects(pos + worldStepX, pos, distance, normal) && if (flipped ? (spanner->intersects(pos + worldStepX, pos, distance, normal) &&
@ -2311,16 +2319,14 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
} }
} }
} }
bool nextSetY = (entryDest != stackDest->getEntryData() + stackDest->getEntryCount() - 1 && bool nextAlphaY = stackDest->getEntryAlpha(y + 1, voxelHeight);
(entryDest + 1)->isSet()); if (nextAlphaY == currentAlpha) {
if (nextSetY == currentSet) {
entryDest->hermiteY = 0; entryDest->hermiteY = 0;
} else { } else {
bool flipped = (erase == nextSetY);
float oldDistance = flipped ? 0.0f : 1.0f; float oldDistance = flipped ? 0.0f : 1.0f;
if (currentSet == oldCurrentSet && nextSetY == isSet(oldStackContents, stackWidth, if (currentAlpha == oldCurrentAlpha && nextAlphaY == oldStackContents.at((int)stackZ * stackWidth +
(int)stackX, y + 1, (int)stackZ)) { (int)stackX).getEntryAlpha(y + 1, oldVoxelHeight) && entryDest->hermiteY != 0) {
oldDistance = qAlpha(entryDest->hermiteY) / (float)numeric_limits<quint8>::max(); oldDistance = qAlpha(entryDest->hermiteY) / (float)numeric_limits<quint8>::max();
} }
if (flipped ? (spanner->intersects(pos + worldStepY, pos, distance, normal) && if (flipped ? (spanner->intersects(pos + worldStepY, pos, distance, normal) &&
@ -2332,15 +2338,15 @@ HeightfieldNode* HeightfieldNode::setMaterial(const glm::vec3& translation, cons
} }
int nextStackZ = (int)stackZ + 1; int nextStackZ = (int)stackZ + 1;
if (nextStackZ <= innerStackHeight) { if (nextStackZ <= innerStackHeight) {
bool nextSetZ = isSet(newStackContents, stackWidth, (int)stackX, y, nextStackZ); bool nextAlphaZ = newStackContents.at(nextStackZ * stackWidth + (int)stackX).getEntryAlpha(
if (nextSetZ == currentSet) { y, nextVoxelHeightZ);
if (nextAlphaZ == currentAlpha) {
entryDest->hermiteZ = 0; entryDest->hermiteZ = 0;
} else { } else {
bool flipped = (erase == nextSetZ);
float oldDistance = flipped ? 0.0f : 1.0f; float oldDistance = flipped ? 0.0f : 1.0f;
if (currentSet == oldCurrentSet && nextSetZ == isSet(oldStackContents, stackWidth, if (currentAlpha == oldCurrentAlpha && nextAlphaZ == oldStackContents.at(nextStackZ * stackWidth +
(int)stackX, y, nextStackZ)) { (int)stackX).getEntryAlpha(y, oldNextVoxelHeightZ) && entryDest->hermiteZ != 0) {
oldDistance = qAlpha(entryDest->hermiteZ) / (float)numeric_limits<quint8>::max(); oldDistance = qAlpha(entryDest->hermiteZ) / (float)numeric_limits<quint8>::max();
} }
if (flipped ? (spanner->intersects(pos + worldStepZ, pos, distance, normal) && if (flipped ? (spanner->intersects(pos + worldStepZ, pos, distance, normal) &&