Merge pull request #3657 from ey6es/metavoxels

Further incremental improvements to heightfield voxelization.
This commit is contained in:
Philip Rosedale 2014-10-23 21:10:21 -07:00
commit 3f7df5962d
6 changed files with 126 additions and 71 deletions

View file

@ -26,11 +26,14 @@ varying vec4 normal;
void main(void) {
// transform and store the normal for interpolation
vec2 heightCoord = gl_MultiTexCoord0.st;
float deltaX = texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r -
texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r;
float deltaZ = texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r -
texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r;
normal = normalize(gl_ModelViewMatrix * vec4(deltaX, heightScale, deltaZ, 0.0));
vec4 neighborHeights = vec4(texture2D(heightMap, heightCoord - vec2(heightScale, 0.0)).r,
texture2D(heightMap, heightCoord + vec2(heightScale, 0.0)).r,
texture2D(heightMap, heightCoord - vec2(0.0, heightScale)).r,
texture2D(heightMap, heightCoord + vec2(0.0, heightScale)).r);
vec4 neighborsZero = step(1.0 / 255.0, neighborHeights);
normal = normalize(gl_ModelViewMatrix * vec4(
(neighborHeights.x - neighborHeights.y) * neighborsZero.x * neighborsZero.y, heightScale,
(neighborHeights.z - neighborHeights.w) * neighborsZero.z * neighborsZero.w, 0.0));
// add the height to the position
float height = texture2D(heightMap, heightCoord).r;

View file

@ -432,6 +432,8 @@ Menu::Menu() :
QMenu* metavoxelOptionsMenu = developerMenu->addMenu("Metavoxels");
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::DisplayHermiteData, 0, false,
Application::getInstance()->getMetavoxels(), SLOT(refreshVoxelData()));
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderHeightfields, 0, true);
addCheckableActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::RenderDualContourSurfaces, 0, true);
addActionToQMenuAndActionHash(metavoxelOptionsMenu, MenuOption::NetworkSimulator, 0, this,
SLOT(showMetavoxelNetworkSimulator()));

View file

@ -446,8 +446,10 @@ namespace MenuOption {
const QString Quit = "Quit";
const QString ReloadAllScripts = "Reload All Scripts";
const QString RenderBoundingCollisionShapes = "Show Bounding Collision Shapes";
const QString RenderDualContourSurfaces = "Render Dual Contour Surfaces";
const QString RenderFocusIndicator = "Show Eye Focus";
const QString RenderHeadCollisionShapes = "Show Head Collision Shapes";
const QString RenderHeightfields = "Render Heightfields";
const QString RenderLookAtVectors = "Show Look-at Vectors";
const QString RenderSkeletonCollisionShapes = "Show Skeleton Collision Shapes";
const QString RenderResolution = "Scale Resolution";

View file

@ -2772,40 +2772,39 @@ void DefaultMetavoxelRendererImplementation::render(MetavoxelData& data, Metavox
glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
_baseHeightfieldProgram.bind();
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
data.guide(heightfieldRenderVisitor);
_baseHeightfieldProgram.release();
glActiveTexture(GL_TEXTURE2);
glBindTexture(GL_TEXTURE_2D, 0);
glActiveTexture(GL_TEXTURE0);
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderHeightfields)) {
_baseHeightfieldProgram.bind();
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
glDisableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_TEXTURE_COORD_ARRAY);
BufferRenderVisitor heightfieldRenderVisitor(Application::getInstance()->getMetavoxels()->getHeightfieldBufferAttribute());
data.guide(heightfieldRenderVisitor);
glDisableClientState(GL_TEXTURE_COORD_ARRAY);
_baseHeightfieldProgram.release();
}
glEnableClientState(GL_VERTEX_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
_baseVoxelProgram.bind();
BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());
data.guide(voxelRenderVisitor);
_baseVoxelProgram.release();
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderDualContourSurfaces)) {
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_NORMAL_ARRAY);
_baseVoxelProgram.bind();
BufferRenderVisitor voxelRenderVisitor(Application::getInstance()->getMetavoxels()->getVoxelBufferAttribute());
data.guide(voxelRenderVisitor);
_baseVoxelProgram.release();
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
glDisable(GL_ALPHA_TEST);
glDisable(GL_CULL_FACE);
glEnable(GL_BLEND);
glDisableClientState(GL_VERTEX_ARRAY);
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
Application::getInstance()->getTextureCache()->setPrimaryDrawBuffers(true, false);
}

View file

@ -2486,8 +2486,39 @@ bool Heightfield::intersects(const glm::vec3& start, const glm::vec3& end, float
if (!getBounds().findRayIntersection(start, direction, rayDistance) || rayDistance > 1.0f) {
return false;
}
glm::vec3 entry = (start + direction * rayDistance - getBounds().minimum) / _increment;
direction /= _increment;
glm::vec3 entry = start + direction * rayDistance;
const float DISTANCE_THRESHOLD = 0.001f;
if (glm::abs(entry.x - getBounds().minimum.x) < DISTANCE_THRESHOLD) {
normal = glm::vec3(-1.0f, 0.0f, 0.0f);
distance = rayDistance;
return true;
} else if (glm::abs(entry.x - getBounds().maximum.x) < DISTANCE_THRESHOLD) {
normal = glm::vec3(1.0f, 0.0f, 0.0f);
distance = rayDistance;
return true;
} else if (glm::abs(entry.y - getBounds().minimum.y) < DISTANCE_THRESHOLD) {
normal = glm::vec3(0.0f, -1.0f, 0.0f);
distance = rayDistance;
return true;
} else if (glm::abs(entry.y - getBounds().maximum.y) < DISTANCE_THRESHOLD) {
normal = glm::vec3(0.0f, 1.0f, 0.0f);
distance = rayDistance;
return true;
} else if (glm::abs(entry.z - getBounds().minimum.z) < DISTANCE_THRESHOLD) {
normal = glm::vec3(0.0f, 0.0f, -1.0f);
distance = rayDistance;
return true;
} else if (glm::abs(entry.z - getBounds().maximum.z) < DISTANCE_THRESHOLD) {
normal = glm::vec3(0.0f, 0.0f, 1.0f);
distance = rayDistance;
return true;
}
entry = (entry - getBounds().minimum) / _increment;
glm::vec3 floors = glm::floor(entry);
glm::vec3 ceils = glm::ceil(entry);
if (floors.x == ceils.x) {

View file

@ -998,10 +998,13 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
_spannerBounds.maximum = (glm::ceil(_bounds.maximum / increment) + glm::vec3(1.0f, 0.0f, 1.0f)) * increment;
_spannerBounds.minimum.y = bounds.minimum.y;
_spannerBounds.maximum.y = bounds.maximum.y;
_heightfieldWidth = (int)glm::round((_spannerBounds.maximum.x - _spannerBounds.minimum.x) / increment) + 1;
_heightfieldHeight = (int)glm::round((_spannerBounds.maximum.z - _spannerBounds.minimum.z) / increment) + 1;
_heightfieldWidth = (int)glm::round((_spannerBounds.maximum.x - _spannerBounds.minimum.x) / increment);
_heightfieldHeight = (int)glm::round((_spannerBounds.maximum.z - _spannerBounds.minimum.z) / increment);
int heightfieldArea = _heightfieldWidth * _heightfieldHeight;
_spanner = spanner = new Heightfield(_spannerBounds, increment, QByteArray(heightfieldArea, 0),
Box innerBounds = _spannerBounds;
innerBounds.maximum.x -= increment;
innerBounds.maximum.z -= increment;
_spanner = spanner = new Heightfield(innerBounds, increment, QByteArray(heightfieldArea, 0),
QByteArray(heightfieldArea * DataBlock::COLOR_BYTES, 0), QByteArray(heightfieldArea, 0),
QVector<SharedObjectPointer>());
}
@ -1049,18 +1052,20 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
}
// if all is gone, clear the node
if (!foundNonZero) {
info.outputValues[0] = AttributeValue(_outputs.at(0),
encodeInline<HeightfieldHeightDataPointer>(HeightfieldHeightDataPointer()));
info.outputValues[1] = AttributeValue(_outputs.at(1),
encodeInline<HeightfieldColorDataPointer>(HeightfieldColorDataPointer()));
info.outputValues[2] = AttributeValue(_outputs.at(2),
encodeInline<HeightfieldMaterialDataPointer>(HeightfieldMaterialDataPointer()));
return STOP_RECURSION;
if (foundNonZero) {
HeightfieldHeightDataPointer newHeightPointer(new HeightfieldHeightData(contents));
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldHeightDataPointer>(newHeightPointer));
} else {
info.outputValues[0] = AttributeValue(_outputs.at(0));
}
HeightfieldHeightDataPointer newHeightPointer(new HeightfieldHeightData(contents));
info.outputValues[0] = AttributeValue(_outputs.at(0), encodeInline<HeightfieldHeightDataPointer>(newHeightPointer));
// allow a border for what we clear in terms of color/material
innerBounds.minimum.x += increment;
innerBounds.minimum.z += increment;
innerBounds.maximum.x -= increment;
innerBounds.maximum.z -= increment;
innerOverlap = bounds.getIntersection(innerBounds);
HeightfieldColorDataPointer colorPointer = info.inputValues.at(1).getInlineValue<HeightfieldColorDataPointer>();
if (colorPointer) {
@ -1083,18 +1088,25 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
memcpy(dest, src, destWidth * DataBlock::COLOR_BYTES);
}
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
dest = contents.data() + (destY * size + destX) * DataBlock::COLOR_BYTES;
for (int y = 0; y < destHeight; y++, dest += size * DataBlock::COLOR_BYTES) {
memset(dest, 0, destWidth * DataBlock::COLOR_BYTES);
if (foundNonZero) {
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
if (destWidth > 0 && destHeight > 0) {
dest = contents.data() + (destY * size + destX) * DataBlock::COLOR_BYTES;
for (int y = 0; y < destHeight; y++, dest += size * DataBlock::COLOR_BYTES) {
memset(dest, 0, destWidth * DataBlock::COLOR_BYTES);
}
HeightfieldColorDataPointer newColorPointer(new HeightfieldColorData(contents));
info.outputValues[1] = AttributeValue(_outputs.at(1),
encodeInline<HeightfieldColorDataPointer>(newColorPointer));
}
} else {
info.outputValues[1] = AttributeValue(_outputs.at(1));
}
HeightfieldColorDataPointer newColorPointer(new HeightfieldColorData(contents));
info.outputValues[1] = AttributeValue(_outputs.at(1), encodeInline<HeightfieldColorDataPointer>(newColorPointer));
}
HeightfieldMaterialDataPointer materialPointer = info.inputValues.at(2).getInlineValue<HeightfieldMaterialDataPointer>();
@ -1130,20 +1142,26 @@ int HeightfieldClearFetchVisitor::visit(MetavoxelInfo& info) {
}
}
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
dest = (uchar*)contents.data() + destY * size + destX;
for (int y = 0; y < destHeight; y++, dest += size) {
memset(dest, 0, destWidth);
if (foundNonZero) {
destX = (innerOverlap.minimum.x - info.minimum.x) * heightScale;
destY = (innerOverlap.minimum.z - info.minimum.z) * heightScale;
destWidth = glm::ceil((innerOverlap.maximum.x - innerOverlap.minimum.x) * heightScale);
destHeight = glm::ceil((innerOverlap.maximum.z - innerOverlap.minimum.z) * heightScale);
if (destWidth > 0 && destHeight > 0) {
dest = (uchar*)contents.data() + destY * size + destX;
for (int y = 0; y < destHeight; y++, dest += size) {
memset(dest, 0, destWidth);
}
clearUnusedMaterials(materials, contents);
HeightfieldMaterialDataPointer newMaterialPointer(new HeightfieldMaterialData(contents, materials));
info.outputValues[2] = AttributeValue(_outputs.at(2),
encodeInline<HeightfieldMaterialDataPointer>(newMaterialPointer));
}
} else {
info.outputValues[2] = AttributeValue(_outputs.at(2));
}
clearUnusedMaterials(materials, contents);
HeightfieldMaterialDataPointer newMaterialPointer(new HeightfieldMaterialData(contents, materials));
info.outputValues[2] = AttributeValue(_outputs.at(2),
encodeInline<HeightfieldMaterialDataPointer>(newMaterialPointer));
}
return STOP_RECURSION;