Feature/interactionsphere (#1561)

* Add ability to render the bounding sphere as a debug option
* Separate boundingsphere and interactionspheres
* Correctly compute BoundingSpheres for more renderables (RenderablePlanesCloud, RenderableOrbitalKepler)
This commit is contained in:
Alexander Bock
2021-04-26 13:13:36 +02:00
committed by GitHub
parent 32b6a69900
commit 2aa540a112
30 changed files with 566 additions and 210 deletions

View File

@@ -381,6 +381,8 @@ RenderableAtmosphere::RenderableAtmosphere(const ghoul::Dictionary& dictionary)
_hardShadowsEnabled.onChange(updateWithoutCalculation);
addProperty(_hardShadowsEnabled);
}
setBoundingSphere(_planetRadius * 1000.0);
}
void RenderableAtmosphere::deinitializeGL() {

View File

@@ -215,8 +215,11 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
}
addProperty(_orientation);
_size.onChange([this]() {
setBoundingSphere(_size);
_sphereIsDirty = true;
});
addProperty(_size);
_size.onChange([this]() { _sphereIsDirty = true; });
addProperty(_segments);
_segments.onChange([this]() { _sphereIsDirty = true; });
@@ -257,6 +260,7 @@ RenderableSphere::RenderableSphere(const ghoul::Dictionary& dictionary)
setRenderBin(Renderable::RenderBin::Background);
}
setBoundingSphere(_size);
setRenderBinFromOpacity();
}

View File

@@ -767,31 +767,6 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
const glm::dvec3& orthoUp,
float fadeInVariable)
{
float scale = 0.f;
switch (_unit) {
case Meter:
scale = 1.f;
break;
case Kilometer:
scale = 1e3f;
break;
case Parsec:
scale = static_cast<float>(PARSEC);
break;
case Kiloparsec:
scale = static_cast<float>(1e3 * PARSEC);
break;
case Megaparsec:
scale = static_cast<float>(1e6 * PARSEC);
break;
case Gigaparsec:
scale = static_cast<float>(1e9 * PARSEC);
break;
case GigalightYears:
scale = static_cast<float>(306391534.73091 * PARSEC);
break;
}
glm::vec4 textColor = glm::vec4(
glm::vec3(_textColor),
_textOpacity * fadeInVariable
@@ -813,7 +788,7 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
for (const std::pair<glm::vec3, std::string>& pair : _labelData) {
//glm::vec3 scaledPos(_transformationMatrix * glm::dvec4(pair.first, 1.0));
glm::vec3 scaledPos(pair.first);
scaledPos *= scale;
scaledPos *= unitToMeter(_unit);
ghoul::fontrendering::FontRenderer::defaultProjectionRenderer().render(
*_font,
scaledPos,
@@ -825,36 +800,11 @@ void RenderableBillboardsCloud::renderLabels(const RenderData& data,
}
void RenderableBillboardsCloud::render(const RenderData& data, RendererTasks&) {
float scale = 0.f;
switch (_unit) {
case Meter:
scale = 1.f;
break;
case Kilometer:
scale = 1e3f;
break;
case Parsec:
scale = static_cast<float>(PARSEC);
break;
case Kiloparsec:
scale = static_cast<float>(1e3 * PARSEC);
break;
case Megaparsec:
scale = static_cast<float>(1e6 * PARSEC);
break;
case Gigaparsec:
scale = static_cast<float>(1e9 * PARSEC);
break;
case GigalightYears:
scale = static_cast<float>(306391534.73091 * PARSEC);
break;
}
float fadeInVariable = 1.f;
if (!_disableFadeInDistance) {
float distCamera = static_cast<float>(glm::length(data.camera.positionVec3()));
const glm::vec2 fadeRange = _fadeInDistance;
const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale);
const float a = 1.f / ((fadeRange.y - fadeRange.x) * unitToMeter(_unit));
const float b = -(fadeRange.x / (fadeRange.y - fadeRange.x));
const float funcValue = a * distCamera + b;
fadeInVariable *= funcValue > 1.f ? 1.f : funcValue;
@@ -1488,6 +1438,19 @@ bool RenderableBillboardsCloud::saveCachedFile(const std::string& file) const {
return fileStream.good();
}
double RenderableBillboardsCloud::unitToMeter(Unit unit) const {
switch (_unit) {
case Meter: return 1.0;
case Kilometer: return 1e3;
case Parsec: return PARSEC;
case Kiloparsec: return 1000 * PARSEC;
case Megaparsec: return 1e6 * PARSEC;
case Gigaparsec: return 1e9 * PARSEC;
case GigalightYears: return 306391534.73091 * PARSEC;
default: throw ghoul::MissingCaseException();
}
}
void RenderableBillboardsCloud::createDataSlice() {
ZoneScoped
@@ -1516,7 +1479,7 @@ void RenderableBillboardsCloud::createDataSlice() {
_slicedData.push_back(_fullData[i + 3 + datavarInUse]);
};
auto addPosition = [&](const glm::vec4 &pos) {
auto addPosition = [&](const glm::vec4& pos) {
for (int j = 0; j < 4; ++j) {
_slicedData.push_back(pos[j]);
}
@@ -1531,17 +1494,24 @@ void RenderableBillboardsCloud::createDataSlice() {
minColorIdx = colorIdx < minColorIdx ? colorIdx : minColorIdx;
}
double maxRadius = 0.0;
float biggestCoord = -1.f;
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerAstronomicalObject) {
glm::dvec4 transformedPos = _transformationMatrix * glm::dvec4(
glm::vec3 transformedPos = glm::vec3(_transformationMatrix * glm::vec4(
_fullData[i + 0],
_fullData[i + 1],
_fullData[i + 2],
1.0
);
// W-normalization
transformedPos /= transformedPos.w;
glm::vec4 position(glm::vec3(transformedPos), static_cast<float>(_unit));
));
glm::vec4 position(transformedPos, static_cast<float>(_unit));
const double unitMeter = unitToMeter(_unit);
glm::dvec3 p = glm::dvec3(position) * unitMeter;
const double r = glm::length(p);
if (r > maxRadius) {
maxRadius = r;
}
if (_hasColorMapFile) {
for (int j = 0; j < 4; ++j) {
@@ -1623,6 +1593,7 @@ void RenderableBillboardsCloud::createDataSlice() {
addPosition(position);
}
}
setBoundingSphere(maxRadius);
_fadeInDistance.setMaxValue(glm::vec2(10.f * biggestCoord));
}

View File

@@ -76,6 +76,7 @@ private:
Gigaparsec = 5,
GigalightYears = 6
};
double unitToMeter(Unit unit) const;
void createDataSlice();
void createPolygonTexture();

View File

@@ -572,35 +572,12 @@ void RenderablePlanesCloud::renderLabels(const RenderData& data,
}
void RenderablePlanesCloud::render(const RenderData& data, RendererTasks&) {
float scale = 0.f;
switch (_unit) {
case Meter:
scale = 1.f;
break;
case Kilometer:
scale = 1e3f;
break;
case Parsec:
scale = static_cast<float>(PARSEC);
break;
case Kiloparsec:
scale = static_cast<float>(1e3 * PARSEC);
break;
case Megaparsec:
scale = static_cast<float>(1e6 * PARSEC);
break;
case Gigaparsec:
scale = static_cast<float>(1e9 * PARSEC);
break;
case GigalightYears:
scale = static_cast<float>(306391534.73091 * PARSEC);
break;
}
const double scale = unitToMeter(_unit);
float fadeInVariable = 1.f;
if (!_disableFadeInDistance) {
float distCamera = static_cast<float>(glm::length(data.camera.positionVec3()));
distCamera /= scale;
distCamera = static_cast<float>(distCamera / scale);
const glm::vec2 fadeRange = _fadeInDistance;
//const float a = 1.f / ((fadeRange.y - fadeRange.x) * scale);
const float a = 1.f / ((fadeRange.y - fadeRange.x));
@@ -1095,16 +1072,37 @@ bool RenderablePlanesCloud::saveCachedFile(const std::string& file) const {
}
}
double RenderablePlanesCloud::unitToMeter(Unit unit) const {
switch (_unit) {
case Meter: return 1.0;
case Kilometer: return 1e3;
case Parsec: return PARSEC;
case Kiloparsec: return 1000 * PARSEC;
case Megaparsec: return 1e6 * PARSEC;
case Gigaparsec: return 1e9 * PARSEC;
case GigalightYears: return 306391534.73091 * PARSEC;
default: throw ghoul::MissingCaseException();
}
}
void RenderablePlanesCloud::createPlanes() {
if (_dataIsDirty && _hasSpeckFile) {
const double scale = unitToMeter(_unit);
LDEBUG("Creating planes...");
float maxSize = 0.f;
double maxRadius = 0.0;
for (size_t p = 0; p < _fullData.size(); p += _nValuesPerAstronomicalObject) {
const glm::vec4 transformedPos = glm::vec4(
_transformationMatrix *
glm::dvec4(_fullData[p + 0], _fullData[p + 1], _fullData[p + 2], 1.0)
);
const double r = glm::length(glm::dvec3(transformedPos) * scale);
if (r > maxRadius) {
maxRadius = r;
}
// Plane vectors u and v
glm::vec4 u = glm::vec4(
_transformationMatrix *
@@ -1145,31 +1143,6 @@ void RenderablePlanesCloud::createPlanes() {
glm::vec4 vertex2 = transformedPos - u + v;
glm::vec4 vertex4 = transformedPos + u - v;
float scale = 0.f;
switch (_unit) {
case Meter:
scale = 1.f;
break;
case Kilometer:
scale = 1e3f;
break;
case Parsec:
scale = static_cast<float>(PARSEC);
break;
case Kiloparsec:
scale = static_cast<float>(1e3 * PARSEC);
break;
case Megaparsec:
scale = static_cast<float>(1e6 * PARSEC);
break;
case Gigaparsec:
scale = static_cast<float>(1e9 * PARSEC);
break;
case GigalightYears:
scale = static_cast<float>(306391534.73091 * PARSEC);
break;
}
for (int i = 0; i < 3; ++i) {
maxSize = std::max(maxSize, vertex0[i]);
maxSize = std::max(maxSize, vertex1[i]);
@@ -1252,6 +1225,7 @@ void RenderablePlanesCloud::createPlanes() {
_dataIsDirty = false;
setBoundingSphere(maxRadius * _scaleFactor);
_fadeInDistance.setMaxValue(glm::vec2(10.f * maxSize));
}

View File

@@ -80,6 +80,7 @@ private:
Gigaparsec = 5,
GigalightYears = 6
};
double unitToMeter(Unit unit) const;
struct PlaneAggregate {
int textureIndex;

View File

@@ -544,12 +544,12 @@ RenderableGlobe::RenderableGlobe(const ghoul::Dictionary& dictionary)
if (p.radii.has_value()) {
if (std::holds_alternative<glm::dvec3>(*p.radii)) {
_ellipsoid = Ellipsoid(std::get<glm::dvec3>(*p.radii));
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
setBoundingSphere(_ellipsoid.maximumRadius());
}
else if (std::holds_alternative<double>(*p.radii)) {
const double radius = std::get<double>(*p.radii);
_ellipsoid = Ellipsoid({ radius, radius, radius });
setBoundingSphere(static_cast<float>(_ellipsoid.maximumRadius()));
setBoundingSphere(_ellipsoid.maximumRadius());
}
else {
throw ghoul::MissingCaseException();
@@ -843,9 +843,14 @@ void RenderableGlobe::update(const UpdateData& data) {
);
}
setBoundingSphere(static_cast<float>(
_ellipsoid.maximumRadius() * glm::compMax(data.modelTransform.scale)
));
double bs = _ellipsoid.maximumRadius() * glm::compMax(data.modelTransform.scale);
if (_hasRings) {
const double ringSize = _ringsComponent.size();
if (ringSize > bs) {
bs = ringSize;
}
}
setBoundingSphere(bs);
glm::dmat4 translation =
glm::translate(glm::dmat4(1.0), data.modelTransform.translation);
@@ -1831,7 +1836,7 @@ SurfacePositionHandle RenderableGlobe::calculateSurfacePositionHandle(
double heightToSurface = getHeight(targetModelSpace);
heightToSurface = glm::isnan(heightToSurface) ? 0.0 : heightToSurface;
centerToEllipsoidSurface = glm::isnan(glm::length(centerToEllipsoidSurface)) ?
(glm::dvec3(0.0, 1.0, 0.0) * static_cast<double>(boundingSphere())) :
(glm::dvec3(0.0, 1.0, 0.0) * interactionSphere()) :
centerToEllipsoidSurface;
ellipsoidSurfaceOutDirection = glm::isnan(glm::length(ellipsoidSurfaceOutDirection)) ?
glm::dvec3(0.0, 1.0, 0.0) : ellipsoidSurfaceOutDirection;

View File

@@ -866,4 +866,8 @@ bool RingsComponent::isEnabled() const {
return _enabled;
}
double RingsComponent::size() const {
return _size;
}
} // namespace openspace

View File

@@ -71,6 +71,7 @@ public:
static documentation::Documentation Documentation();
bool isEnabled() const;
double size() const;
private:
void loadTexture();

View File

@@ -143,6 +143,7 @@ RenderableHabitableZone::RenderableHabitableZone(const ghoul::Dictionary& dictio
_width.setReadOnly(true);
computeZone();
setBoundingSphere(_size);
}
void RenderableHabitableZone::render(const RenderData& data, RendererTasks&) {

View File

@@ -476,6 +476,14 @@ void RenderableOrbitalKepler::initializeGL() {
_uniformCache.opacity = _programObject->uniformLocation("opacity");
updateBuffers();
double maxSemiMajorAxis = 0.0;
for (const KeplerParameters& kp : _data) {
if (kp.semiMajorAxis > maxSemiMajorAxis) {
maxSemiMajorAxis = kp.semiMajorAxis;
}
}
setBoundingSphere(maxSemiMajorAxis * 1000);
}
void RenderableOrbitalKepler::deinitializeGL() {

View File

@@ -1486,14 +1486,21 @@ void RenderableStars::createDataSlice(ColorOption option) {
-std::numeric_limits<float>::max()
);
double maxRadius = 0.0;
for (size_t i = 0; i < _fullData.size(); i += _nValuesPerStar) {
glm::vec3 position = glm::vec3(
glm::dvec3 position = glm::dvec3(
_fullData[i + 0],
_fullData[i + 1],
_fullData[i + 2]
);
position *= openspace::distanceconstants::Parsec;
const double r = glm::length(position);
if (r > maxRadius) {
maxRadius = r;
}
switch (option) {
case ColorOption::Color:
case ColorOption::FixedColor:
@@ -1503,7 +1510,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
std::array<float, sizeof(ColorVBOLayout) / sizeof(float)> data;
} layout;
layout.value.position = { { position[0], position[1], position[2] } };
layout.value.position = { {
static_cast<float>(position[0]),
static_cast<float>(position[1]),
static_cast<float>(position[2])
}};
if (_enableTestGrid) {
float sunColor = 0.650f;
@@ -1531,7 +1542,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
std::array<float, sizeof(VelocityVBOLayout) / sizeof(float)> data;
} layout;
layout.value.position = { { position[0], position[1], position[2] } };
layout.value.position = {{
static_cast<float>(position[0]),
static_cast<float>(position[1]),
static_cast<float>(position[2])
}};
layout.value.value = _fullData[i + _bvColorArrayPos];
layout.value.luminance = _fullData[i + _lumArrayPos];
@@ -1556,7 +1571,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
std::array<float, sizeof(SpeedVBOLayout) / sizeof(float)> data;
} layout;
layout.value.position = { { position[0], position[1], position[2] } };
layout.value.position = {{
static_cast<float>(position[0]),
static_cast<float>(position[1]),
static_cast<float>(position[2])
}};
layout.value.value = _fullData[i + _bvColorArrayPos];
layout.value.luminance = _fullData[i + _lumArrayPos];
@@ -1579,7 +1598,11 @@ void RenderableStars::createDataSlice(ColorOption option) {
std::array<float, sizeof(OtherDataLayout)> data;
} layout = {};
layout.value.position = { { position[0], position[1], position[2] } };
layout.value.position = {{
static_cast<float>(position[0]),
static_cast<float>(position[1]),
static_cast<float>(position[2])
}};
int index = _otherDataOption.value();
// plus 3 because of the position
@@ -1612,6 +1635,8 @@ void RenderableStars::createDataSlice(ColorOption option) {
}
}
}
setBoundingSphere(maxRadius);
}
} // namespace openspace

View File

@@ -146,7 +146,7 @@ void gradient(double* g, double* par, int x, void* fdata, LMstat* lmstat) {
FunctionData* ptr = reinterpret_cast<FunctionData*>(fdata);
double f0 = distToMinimize(par, x, fdata, lmstat);
// scale value to find minimum step size h, dependant on planet size
double scale = log10(ptr->node->boundingSphere());
double scale = log10(ptr->node->interactionSphere());
std::vector<double> dPar(ptr->nDOF, 0.0);
dPar.assign(par, par + ptr->nDOF);

View File

@@ -507,15 +507,15 @@ void TouchInteraction::findSelectedNode(const std::vector<TouchInputHolder>& lis
size_t id = inputHolder.fingerId();
for (SceneGraphNode* node : selectableNodes) {
double boundingSphereSquared = static_cast<double>(node->boundingSphere()) *
static_cast<double>(node->boundingSphere());
double interactionSphereSquared =
node->interactionSphere() * node->interactionSphere();
glm::dvec3 camToSelectable = node->worldPosition() - camPos;
double intersectionDist = 0.0;
const bool intersected = glm::intersectRaySphere(
camPos,
raytrace,
node->worldPosition(),
boundingSphereSquared,
interactionSphereSquared,
intersectionDist
);
if (intersected) {
@@ -921,7 +921,7 @@ double TouchInteraction::computeTapZoomDistance(double zoomGain) {
global::navigationHandler->orbitalNavigator().anchorNode()->worldPosition()
);
dist -= anchor->boundingSphere();
dist -= anchor->interactionSphere();
double newVelocity = dist * _tapZoomFactor;
newVelocity *= std::max(_touchScreenSize.value() * 0.1, 1.0);
@@ -962,9 +962,9 @@ void TouchInteraction::step(double dt, bool directTouch) {
dquat globalCamRot = normalize(quat_cast(inverse(lookAtMat)));
dquat localCamRot = inverse(globalCamRot) * _camera->rotationQuaternion();
const double boundingSphere = anchor->boundingSphere();
const double distance = std::max(length(centerToCamera) - boundingSphere, 0.0);
_currentRadius = boundingSphere /
const double interactionSphere = anchor->interactionSphere();
const double distance = std::max(length(centerToCamera) - interactionSphere, 0.0);
_currentRadius = interactionSphere /
std::max(distance * _projectionScaleFactor, 1.0);
{
@@ -1010,7 +1010,7 @@ void TouchInteraction::step(double dt, bool directTouch) {
// This is a rough estimate of the node surface
// If nobody has set another zoom in limit, use this as default zoom in bounds
double zoomInBounds = boundingSphere * _zoomBoundarySphereMultiplier;
double zoomInBounds = interactionSphere * _zoomBoundarySphereMultiplier;
bool isZoomInLimitSet = (_zoomInLimit.value() >= 0.0);
if (isZoomInLimitSet && _zoomInLimit.value() < zoomInBounds) {
@@ -1049,7 +1049,7 @@ void TouchInteraction::step(double dt, bool directTouch) {
double zoomVelocity = _vel.zoom;
if (!directTouch) {
const double distanceFromSurface =
length(currentPosDistance) - anchor->boundingSphere();
length(currentPosDistance) - anchor->interactionSphere();
if (distanceFromSurface > 0.1) {
const double ratioOfDistanceToNodeVsSurf =
length(currentPosDistance) / distanceFromSurface;