Celestia

Форк
0
/
galaxy.cpp 
213 строк · 6.1 Кб
1
// galaxy.cpp
2
//
3
// Copyright (C) 2001-2009, the Celestia Development Team
4
// Original version by Chris Laurel, Fridger Schrempp, and Toti
5
//
6
// This program is free software; you can redistribute it and/or
7
// modify it under the terms of the GNU General Public License
8
// as published by the Free Software Foundation; either version 2
9
// of the License, or (at your option) any later version.
10

11
#include <algorithm>
12
#include <fmt/printf.h>
13

14
#include <celmath/intersect.h>
15
#include <celmath/ray.h>
16
#include <celutil/gettext.h>
17
#include "galaxy.h"
18
#include "galaxyform.h"
19
#include "hash.h"
20
#include "render.h"
21

22
using namespace std::string_view_literals;
23

24
using celestia::engine::GalacticFormManager;
25
namespace math = celestia::math;
26

27
struct GalaxyTypeName
28
{
29
    const char* name;
30
    GalaxyType type;
31
};
32

33
constexpr std::array GalaxyTypeNames =
34
{
35
    GalaxyTypeName{ "Irr", GalaxyType::Irr },
36
    GalaxyTypeName{ "S0",  GalaxyType::S0 },
37
    GalaxyTypeName{ "Sa",  GalaxyType::Sa },
38
    GalaxyTypeName{ "Sb",  GalaxyType::Sb },
39
    GalaxyTypeName{ "Sc",  GalaxyType::Sc },
40
    GalaxyTypeName{ "SBa", GalaxyType::SBa },
41
    GalaxyTypeName{ "SBb", GalaxyType::SBb },
42
    GalaxyTypeName{ "SBc", GalaxyType::SBc },
43
    GalaxyTypeName{ "E0",  GalaxyType::E0 },
44
    GalaxyTypeName{ "E1",  GalaxyType::E1 },
45
    GalaxyTypeName{ "E2",  GalaxyType::E2 },
46
    GalaxyTypeName{ "E3",  GalaxyType::E3 },
47
    GalaxyTypeName{ "E4",  GalaxyType::E4 },
48
    GalaxyTypeName{ "E5",  GalaxyType::E5 },
49
    GalaxyTypeName{ "E6",  GalaxyType::E6 },
50
    GalaxyTypeName{ "E7",  GalaxyType::E7 },
51
};
52

53
float Galaxy::lightGain = 0.0f;
54

55
float Galaxy::getDetail() const
56
{
57
    return detail;
58
}
59

60
void Galaxy::setDetail(float d)
61
{
62
    detail = d;
63
}
64

65
const char* Galaxy::getType() const
66
{
67
    return GalaxyTypeNames[static_cast<std::size_t>(type)].name;
68
}
69

70
void Galaxy::setType(const std::string& typeStr)
71
{
72
    type = GalaxyType::Irr;
73
    auto iter = std::find_if(std::begin(GalaxyTypeNames), std::end(GalaxyTypeNames),
74
                             [&](const GalaxyTypeName& g) { return g.name == typeStr; });
75
    if (iter != std::end(GalaxyTypeNames))
76
        type = iter->type;
77
}
78

79
void Galaxy::setForm(const fs::path& customTmpName, const fs::path& resDir)
80
{
81
    if (customTmpName.empty())
82
    {
83
        form = static_cast<int>(type);
84
    }
85
    else
86
    {
87
        if (fs::path fullName = resDir / customTmpName; fs::exists(fullName))
88
            form = GalacticFormManager::get()->getCustomForm(fullName);
89
        else
90
            form = GalacticFormManager::get()->getCustomForm(fs::path("models") / customTmpName);
91
    }
92
}
93

94
std::string Galaxy::getDescription() const
95
{
96
    return fmt::sprintf(_("Galaxy (Hubble type: %s)"), getType());
97
}
98

99
DeepSkyObjectType Galaxy::getObjType() const
100
{
101
    return DeepSkyObjectType::Galaxy;
102
}
103

104
int Galaxy::getFormId() const
105
{
106
    return form;
107
}
108

109
bool Galaxy::pick(const Eigen::ParametrizedLine<double, 3>& ray,
110
                  double& distanceToPicker,
111
                  double& cosAngleToBoundCenter) const
112
{
113
    const auto* galacticForm = GalacticFormManager::get()->getForm(form);
114
    if (galacticForm == nullptr || !isVisible())
115
        return false;
116

117
    // The ellipsoid should be slightly larger to compensate for the fact
118
    // that blobs are considered points when galaxies are built, but have size
119
    // when they are drawn.
120
    float yscale = (type > GalaxyType::Irr && type < GalaxyType::E0)
121
        ? kMaxSpiralThickness
122
        : galacticForm->scale.y() + kRadiusCorrection;
123
    Eigen::Vector3d ellipsoidAxes(getRadius()*(galacticForm->scale.x() + kRadiusCorrection),
124
                                  getRadius()* yscale,
125
                                  getRadius()*(galacticForm->scale.z() + kRadiusCorrection));
126
    Eigen::Matrix3d rotation = getOrientation().cast<double>().toRotationMatrix();
127

128
    return math::testIntersection(
129
        math::transformRay(Eigen::ParametrizedLine<double, 3>(ray.origin() - getPosition(), ray.direction()),
130
                           rotation),
131
        math::Ellipsoidd(ellipsoidAxes),
132
        distanceToPicker,
133
        cosAngleToBoundCenter);
134
}
135

136
bool Galaxy::load(const AssociativeArray* params, const fs::path& resPath)
137
{
138
    setDetail(params->getNumber<float>("Detail").value_or(1.0f));
139

140
    if (const auto* typeName = params->getString("Type"); typeName == nullptr)
141
        setType({});
142
    else
143
        setType(*typeName);
144

145

146
    if (auto customTmpName = params->getPath("CustomTemplate"sv); customTmpName.has_value())
147
        setForm(customTmpName.value(), resPath);
148
    else
149
        setForm({});
150

151
    return DeepSkyObject::load(params, resPath);
152
}
153

154
GalaxyType Galaxy::getGalaxyType() const
155
{
156
    return type;
157
}
158

159
float Galaxy::getBrightnessCorrection(const Eigen::Vector3f &offset) const
160
{
161
    Eigen::Quaternionf orientation = getOrientation().conjugate();
162

163
    // corrections to avoid excessive brightening if viewed e.g. edge-on
164
    float brightness_corr = 1.0f;
165
    if (type != GalaxyType::Irr && (type < GalaxyType::E0 || type > GalaxyType::E3)) // all galaxies, except ~round elliptics and irregular
166
    {
167
        float cosi      = (orientation * Eigen::Vector3f::UnitY()).dot(offset) / offset.norm();
168
        brightness_corr = std::max(0.2f, std::sqrt(std::abs(cosi)));
169
        if (type > GalaxyType::E3) // only elliptics with higher ellipticities
170
        {
171
            float cosi      = (orientation * Eigen::Vector3f::UnitX()).dot(offset) / offset.norm();
172
            brightness_corr = std::max(0.45f, brightness_corr * std::abs(cosi));
173
        }
174
    }
175

176
    float btot = (type == GalaxyType::Irr || type >= GalaxyType::E0) ? 2.5f : 5.0f;
177
    return (4.0f * lightGain + 1.0f) * btot * brightness_corr;
178
}
179

180
std::uint64_t Galaxy::getRenderMask() const
181
{
182
    return Renderer::ShowGalaxies;
183
}
184

185
unsigned int Galaxy::getLabelMask() const
186
{
187
    return Renderer::GalaxyLabels;
188
}
189

190
void Galaxy::increaseLightGain()
191
{
192
    lightGain = std::min(1.0f, lightGain + 0.05f);
193
}
194

195
void Galaxy::decreaseLightGain()
196
{
197
    lightGain = std::max(0.0f, lightGain - 0.05f);
198
}
199

200
float Galaxy::getLightGain()
201
{
202
    return lightGain;
203
}
204

205
void Galaxy::setLightGain(float lg)
206
{
207
    lightGain = std::clamp(lg, 0.0f, 1.0f);
208
}
209

210
std::ostream& operator<<(std::ostream& s, const GalaxyType& sc)
211
{
212
    return s << GalaxyTypeNames[static_cast<std::size_t>(sc)].name;
213
}
214

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.