Try to make RenderableOrbitDisc more intuitive

* The size now matches the semi-major axis
* Avoid re-setting size value in constructor
* Avoid inconsistent units for offsets and size (previously AU and meter)
This commit is contained in:
Emma Broman
2020-12-11 14:13:36 +01:00
parent 05651d1aa3
commit 92085847f2
4 changed files with 46 additions and 38 deletions

View File

@@ -58,7 +58,7 @@ constexpr const char* DiscTextureFile =
constexpr const char* HabitableZoneTextureFile =
"${SYNC}/http/exoplanets_textures/1/hz_disc_texture.png";
const float AstronomicalUnit = static_cast<float>(distanceconstants::AstronomicalUnit);
const float AU = static_cast<float>(distanceconstants::AstronomicalUnit);
const float SolarRadius = static_cast<float>(distanceconstants::SolarRadius);
const float JupiterRadius = static_cast<float>(distanceconstants::JupiterRadius);
@@ -280,7 +280,7 @@ void createExoplanetSystem(const std::string& starName) {
std::string enabled;
if (std::isnan(planet.r)) {
if (std::isnan(planet.rStar)) {
planetRadius = planet.a * 0.001f * AstronomicalUnit;
planetRadius = planet.a * 0.001f * AU;
}
else {
planetRadius = planet.rStar * 0.1f * SolarRadius;
@@ -293,7 +293,7 @@ void createExoplanetSystem(const std::string& starName) {
}
const float periodInSeconds = static_cast<float>(planet.per * SecondsPerDay);
const float semiMajorAxisInMeter = planet.a * AstronomicalUnit;
const float semiMajorAxisInMeter = planet.a * AU;
const float semiMajorAxisInKm = semiMajorAxisInMeter * 0.001f;
const std::string planetIdentifier = createIdentifier(planetName);
@@ -373,6 +373,9 @@ void createExoplanetSystem(const std::string& starName) {
);
const glm::dmat3 rotationMat3 = static_cast<glm::dmat3>(rotation);
const float lowerOffset = planet.aLower / planet.a;
const float upperOffset = planet.aUpper / planet.a;
const std::string discNode = "{"
"Identifier = '" + planetIdentifier + "_Disc',"
"Parent = '" + starIdentifier + "',"
@@ -383,8 +386,8 @@ void createExoplanetSystem(const std::string& starName) {
"Size = " + std::to_string(semiMajorAxisInMeter) + ","
"Eccentricity = " + std::to_string(planet.ecc) + ","
"Offset = { " +
std::to_string(planet.aLower) + ", " +
std::to_string(planet.aUpper) +
std::to_string(lowerOffset) + ", " +
std::to_string(upperOffset) +
"}," //min / max extend
"Opacity = 0.3"
"},"
@@ -425,9 +428,11 @@ void createExoplanetSystem(const std::string& starName) {
const glm::dmat4 rotation = computeOrbitPlaneRotationMatrix(meanInclination);
const glm::dmat3 rotationMat3 = static_cast<glm::dmat3>(rotation);
glm::vec2 limits = zone.value();
float half = 0.5f * (limits[1] - limits[0]);
float center = limits[0] + half;
glm::vec2 limitsInMeter = zone.value() * AU;
float half = 0.5f * (limitsInMeter[1] - limitsInMeter[0]);
float center = limitsInMeter[0] + half;
float relativeOffset = half / center;
const std::string zoneDiscNode = "{"
"Identifier = '" + starIdentifier + "_HZ_Disc',"
"Parent = '" + starIdentifier + "',"
@@ -439,11 +444,11 @@ void createExoplanetSystem(const std::string& starName) {
"Rotation = " + ghoul::to_string(rotationMat3) + ""
"},"
"Texture = openspace.absPath('" + HabitableZoneTextureFile + "'),"
"Size = " + std::to_string(center * AstronomicalUnit) + ","
"Size = " + std::to_string(center) + ","
"Eccentricity = 0,"
"Offset = { " +
std::to_string(half) + ", " +
std::to_string(half) +
std::to_string(relativeOffset) + ", " +
std::to_string(relativeOffset) +
"}," //min / max extend
"Opacity = 0.05"
"},"

View File

@@ -50,7 +50,7 @@ namespace {
static const openspace::properties::Property::PropertyInfo SizeInfo = {
"Size",
"Size",
"This value specifies the semi-major axis of the orbit in meter."
"This value specifies the semi-major axis of the orbit, in meter."
};
static const openspace::properties::Property::PropertyInfo EccentricityInfo = {
@@ -63,8 +63,10 @@ namespace {
static const openspace::properties::Property::PropertyInfo OffsetInfo = {
"Offset",
"Offset",
"This value is used to limit the width of the rings. Each of the two values is "
"the lower and the upper uncertainties of the semi-major axis. "
"This property determines the width of the disc. The values specify the lower "
"and upper deviation from the semi major axis, respectively. The values are "
"relative to the size of the semi-major axis. That is, 0 means no deviation "
"from the semi-major axis and 1 is a whole semi-major axis's worth of deviation."
};
} // namespace
@@ -114,7 +116,7 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary)
, _texturePath(TextureInfo)
, _size(SizeInfo, 1.f, 0.f, 3.0e12f)
, _eccentricity(EccentricityInfo, 0.f, 0.f, 1.f)
, _offset(OffsetInfo, glm::vec2(0.f, 1.f), glm::vec2(0.f), glm::vec2(1.f))
, _offset(OffsetInfo, glm::vec2(0.f), glm::vec2(0.f), glm::vec2(1.f))
{
using ghoul::filesystem::File;
@@ -127,16 +129,15 @@ RenderableOrbitDisc::RenderableOrbitDisc(const ghoul::Dictionary& dictionary)
if (dictionary.hasKey(OffsetInfo.identifier)) {
_offset = dictionary.value<glm::vec2>(OffsetInfo.identifier);
}
_offset.onChange([&]() { _planeIsDirty = true; });
addProperty(_offset);
_size = static_cast<float>(dictionary.value<double>(SizeInfo.identifier));
_size = static_cast<float>(
_size + (_offset.value().y * distanceconstants::AstronomicalUnit)
);
setBoundingSphere(_size);
_size.onChange([&]() { _planeIsDirty = true; });
addProperty(_size);
setBoundingSphere(_size + _offset.value().y * _size);
_texturePath = absPath(dictionary.value<std::string>(TextureInfo.identifier));
_textureFile = std::make_unique<File>(_texturePath);
@@ -168,7 +169,7 @@ void RenderableOrbitDisc::initializeGL() {
_uniformCache.modelViewProjection = _shader->uniformLocation(
"modelViewProjectionTransform"
);
_uniformCache.textureOffset = _shader->uniformLocation("textureOffset");
_uniformCache.offset = _shader->uniformLocation("offset");
_uniformCache.opacity = _shader->uniformLocation("opacity");
_uniformCache.texture = _shader->uniformLocation("discTexture");
_uniformCache.eccentricity = _shader->uniformLocation("eccentricity");
@@ -209,7 +210,7 @@ void RenderableOrbitDisc::render(const RenderData& data, RendererTasks&) {
_uniformCache.modelViewProjection,
data.camera.projectionMatrix() * glm::mat4(modelViewTransform)
);
_shader->setUniform(_uniformCache.textureOffset, _offset);
_shader->setUniform(_uniformCache.offset, _offset);
_shader->setUniform(_uniformCache.opacity, _opacity);
_shader->setUniform(_uniformCache.eccentricity, _eccentricity);
_shader->setUniform(_uniformCache.semiMajorAxis, _size);
@@ -241,7 +242,7 @@ void RenderableOrbitDisc::update(const UpdateData&) {
_uniformCache.modelViewProjection = _shader->uniformLocation(
"modelViewProjectionTransform"
);
_uniformCache.textureOffset = _shader->uniformLocation("textureOffset");
_uniformCache.offset = _shader->uniformLocation("offset");
_uniformCache.opacity = _shader->uniformLocation("opacity");
_uniformCache.texture = _shader->uniformLocation("discTexture");
_uniformCache.eccentricity = _shader->uniformLocation("eccentricity");
@@ -283,7 +284,8 @@ void RenderableOrbitDisc::loadTexture() {
}
void RenderableOrbitDisc::createPlane() {
const GLfloat size = _size * (1.f + _eccentricity);
const GLfloat outerDistance = (_size + _offset.value().y * _size);
const GLfloat size = outerDistance * (1.f + _eccentricity);
struct VertexData {
GLfloat x;

View File

@@ -66,8 +66,8 @@ private:
properties::Vec2Property _offset;
std::unique_ptr<ghoul::opengl::ProgramObject> _shader = nullptr;
UniformCache(modelViewProjection, textureOffset, opacity,
texture, eccentricity, semiMajorAxis) _uniformCache;
UniformCache(modelViewProjection, offset, opacity, texture,
eccentricity, semiMajorAxis) _uniformCache;
std::unique_ptr<ghoul::opengl::Texture> _texture = nullptr;
std::unique_ptr<ghoul::filesystem::File> _textureFile;

View File

@@ -29,12 +29,11 @@ in vec2 vs_st;
in vec4 vs_position;
uniform sampler1D discTexture;
uniform vec2 textureOffset;
uniform vec2 offset; // relative to semi major axis
uniform float opacity;
uniform float eccentricity;
uniform float semiMajorAxis;
const float AstronomicalUnit = 149597870700.0; // m
const float Epsilon = 0.0000001;
// Compute semi minor axis from major axis, a, and eccentricity, e
@@ -56,16 +55,15 @@ Fragment getFragment() {
// Moving the origin to the center
vec2 st = (vs_st - vec2(0.5)) * 2.0;
float offsetLower = textureOffset.x;
float offsetUpper = textureOffset.y;
float offsetIntervalSize = offsetLower + offsetUpper;
float offsetLower = offset.x * semiMajorAxis;
float offsetUpper = offset.y * semiMajorAxis;
float AUpper = semiMajorAxis;
float AUpper = semiMajorAxis + offsetUpper;
float BUpper = semiMinorAxis(AUpper, eccentricity);
float CUpper = sqrt(AUpper*AUpper - BUpper*BUpper);
float outerApoapsisDistance = AUpper * (1 + eccentricity);
float ALower = AUpper - AstronomicalUnit * offsetIntervalSize;
float ALower = semiMajorAxis - offsetLower;
float BLower = semiMinorAxis(ALower, eccentricity);
float CLower = sqrt(ALower*ALower - BLower*BLower);
float innerApoapsisDistance = ALower * (1 + eccentricity);
@@ -106,16 +104,19 @@ Fragment getFragment() {
float discWidth = distance(outerPoint, innerPoint);
float distanceFromOuterEdge = distance(outerPoint, st);
float textureCoord = distanceFromOuterEdge / discWidth;
float relativeDistance = distanceFromOuterEdge / discWidth;
// Scale texture coordinate to handle asymmetric offset intervals
float textureMid = offsetUpper / offsetIntervalSize;
// Compute texture coordinate based on the distance to outer edge
float textureCoord = 0.0;
if(textureCoord > textureMid) {
textureCoord = 0.5 + 0.5 * (textureCoord - textureMid) / (1.0 - textureMid);
// The midpoint (textureCoord = 0.5) depends on the ratio between the offsets
// (Note that the texture goes from outer to inner edge of disc)
float midPoint = offsetUpper / (offsetUpper + offsetLower);
if(relativeDistance > midPoint) {
textureCoord = 0.5 + 0.5 * (relativeDistance - midPoint) / (1.0 - midPoint);
}
else {
textureCoord = 0.5 * textureCoord / textureMid;
textureCoord = 0.5 * (relativeDistance / midPoint);
}
vec4 diffuse = texture(discTexture, textureCoord);