mirror of
https://github.com/overte-org/overte.git
synced 2025-08-04 04:23:33 +02:00
If there's no directly intersecting spanner, find the closest heightfield that
we can project onto.
This commit is contained in:
parent
45b36b383c
commit
2497b2fe39
2 changed files with 65 additions and 8 deletions
|
@ -1957,15 +1957,14 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// determine whether we should ignore this vertex because it will be stitched
|
// determine whether we should ignore this vertex because it will be stitched
|
||||||
bool ignore = false;
|
int validCrossings = 0;
|
||||||
for (int i = 0; i < crossingCount; i++) {
|
for (int i = 0; i < crossingCount; i++) {
|
||||||
if (qAlpha(crossings[i].color) == 0) {
|
if (qAlpha(crossings[i].color) != 0) {
|
||||||
ignore = true;
|
validCrossings++;
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
NormalIndex index = { { -1, -1, -1, -1 } };
|
NormalIndex index = { { -1, -1, -1, -1 } };
|
||||||
if (!ignore) {
|
if (validCrossings != 0) {
|
||||||
index.indices[0] = index.indices[1] = index.indices[2] = index.indices[3] = vertices.size();
|
index.indices[0] = index.indices[1] = index.indices[2] = index.indices[3] = vertices.size();
|
||||||
glm::vec3 center;
|
glm::vec3 center;
|
||||||
glm::vec3 normals[MAX_NORMALS_PER_VERTEX];
|
glm::vec3 normals[MAX_NORMALS_PER_VERTEX];
|
||||||
|
@ -1978,6 +1977,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
||||||
int red = 0, green = 0, blue = 0;
|
int red = 0, green = 0, blue = 0;
|
||||||
for (int i = 0; i < crossingCount; i++) {
|
for (int i = 0; i < crossingCount; i++) {
|
||||||
const EdgeCrossing& crossing = crossings[i];
|
const EdgeCrossing& crossing = crossings[i];
|
||||||
|
if (qAlpha(crossing.color) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
center += crossing.point;
|
center += crossing.point;
|
||||||
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
|
@ -2013,7 +2015,7 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
center /= crossingCount;
|
center /= validCrossings;
|
||||||
|
|
||||||
// use a sequence of Givens rotations to perform a QR decomposition
|
// use a sequence of Givens rotations to perform a QR decomposition
|
||||||
// see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf
|
// see http://www.cs.rice.edu/~jwarren/papers/techreport02408.pdf
|
||||||
|
@ -2021,6 +2023,9 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
||||||
glm::vec4 bottom;
|
glm::vec4 bottom;
|
||||||
for (int i = 0; i < crossingCount; i++) {
|
for (int i = 0; i < crossingCount; i++) {
|
||||||
const EdgeCrossing& crossing = crossings[i];
|
const EdgeCrossing& crossing = crossings[i];
|
||||||
|
if (qAlpha(crossing.color) == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center));
|
bottom = glm::vec4(crossing.normal, glm::dot(crossing.normal, crossing.point - center));
|
||||||
|
|
||||||
for (int j = 0; j < 4; j++) {
|
for (int j = 0; j < 4; j++) {
|
||||||
|
@ -2085,8 +2090,8 @@ void HeightfieldNodeRenderer::render(const HeightfieldNodePointer& node, const g
|
||||||
materialWeights *= (numeric_limits<quint8>::max() / totalWeight);
|
materialWeights *= (numeric_limits<quint8>::max() / totalWeight);
|
||||||
}
|
}
|
||||||
VoxelPoint point = { (glm::vec3(clampedX, y, clampedZ) + center) * step,
|
VoxelPoint point = { (glm::vec3(clampedX, y, clampedZ) + center) * step,
|
||||||
{ (quint8)(red / crossingCount), (quint8)(green / crossingCount),
|
{ (quint8)(red / validCrossings), (quint8)(green / validCrossings),
|
||||||
(quint8)(blue / crossingCount) },
|
(quint8)(blue / validCrossings) },
|
||||||
{ (char)(normals[0].x * 127.0f), (char)(normals[0].y * 127.0f),
|
{ (char)(normals[0].x * 127.0f), (char)(normals[0].y * 127.0f),
|
||||||
(char)(normals[0].z * 127.0f) },
|
(char)(normals[0].z * 127.0f) },
|
||||||
{ materials[0], materials[1], materials[2], materials[3] },
|
{ materials[0], materials[1], materials[2], materials[3] },
|
||||||
|
|
|
@ -9,6 +9,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
|
#include <glm/gtx/transform.hpp>
|
||||||
|
|
||||||
#include "MetavoxelMessages.h"
|
#include "MetavoxelMessages.h"
|
||||||
#include "Spanner.h"
|
#include "Spanner.h"
|
||||||
|
|
||||||
|
@ -180,6 +182,50 @@ HeightfieldMaterialSpannerEdit::HeightfieldMaterialSpannerEdit(const SharedObjec
|
||||||
paint(paint) {
|
paint(paint) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class SpannerProjectionFetchVisitor : public SpannerVisitor {
|
||||||
|
public:
|
||||||
|
|
||||||
|
SpannerProjectionFetchVisitor(const Box& bounds, QVector<SharedObjectPointer>& results);
|
||||||
|
|
||||||
|
virtual bool visit(Spanner* spanner);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
const Box& _bounds;
|
||||||
|
QVector<SharedObjectPointer>& _results;
|
||||||
|
float _closestDistance;
|
||||||
|
};
|
||||||
|
|
||||||
|
SpannerProjectionFetchVisitor::SpannerProjectionFetchVisitor(const Box& bounds, QVector<SharedObjectPointer>& results) :
|
||||||
|
SpannerVisitor(QVector<AttributePointer>() << AttributeRegistry::getInstance()->getSpannersAttribute()),
|
||||||
|
_bounds(bounds),
|
||||||
|
_results(results),
|
||||||
|
_closestDistance(FLT_MAX) {
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SpannerProjectionFetchVisitor::visit(Spanner* spanner) {
|
||||||
|
Heightfield* heightfield = qobject_cast<Heightfield*>(spanner);
|
||||||
|
if (!heightfield) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
glm::mat4 transform = glm::scale(1.0f / glm::vec3(heightfield->getScale(),
|
||||||
|
heightfield->getScale() * heightfield->getAspectY(),
|
||||||
|
heightfield->getScale() * heightfield->getAspectZ())) *
|
||||||
|
glm::mat4_cast(glm::inverse(heightfield->getRotation())) * glm::translate(-heightfield->getTranslation());
|
||||||
|
Box transformedBounds = transform * _bounds;
|
||||||
|
if (transformedBounds.maximum.x < 0.0f && transformedBounds.maximum.z < 0.0f &&
|
||||||
|
transformedBounds.minimum.x > 1.0f && transformedBounds.minimum.z > 1.0f) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
float distance = qMin(glm::abs(transformedBounds.minimum.y), glm::abs(transformedBounds.maximum.y));
|
||||||
|
if (distance < _closestDistance) {
|
||||||
|
_results.clear();
|
||||||
|
_results.append(spanner);
|
||||||
|
_closestDistance = distance;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakSharedObjectHash& objects) const {
|
||||||
// make sure the color meets our transparency requirements
|
// make sure the color meets our transparency requirements
|
||||||
QColor color = averageColor;
|
QColor color = averageColor;
|
||||||
|
@ -193,6 +239,12 @@ void HeightfieldMaterialSpannerEdit::apply(MetavoxelData& data, const WeakShared
|
||||||
data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(),
|
data.getIntersecting(AttributeRegistry::getInstance()->getSpannersAttribute(),
|
||||||
static_cast<Spanner*>(spanner.data())->getBounds(), results);
|
static_cast<Spanner*>(spanner.data())->getBounds(), results);
|
||||||
|
|
||||||
|
// if there's nothing intersecting directly, find the closest heightfield that intersects the projection
|
||||||
|
if (results.isEmpty()) {
|
||||||
|
SpannerProjectionFetchVisitor visitor(static_cast<Spanner*>(spanner.data())->getBounds(), results);
|
||||||
|
data.guide(visitor);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (const SharedObjectPointer& result, results) {
|
foreach (const SharedObjectPointer& result, results) {
|
||||||
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material, color, paint);
|
Spanner* newResult = static_cast<Spanner*>(result.data())->setMaterial(spanner, material, color, paint);
|
||||||
if (newResult != result) {
|
if (newResult != result) {
|
||||||
|
|
Loading…
Reference in a new issue