Celestia

Форк
0
/
simulation.cpp 
567 строк · 13.4 Кб
1
// simulation.cpp
2
//
3
// Copyright (C) 2001, Chris Laurel <claurel@shatters.net>
4
//
5
// The core of Celestia--tracks an observer moving through a
6
// stars and their solar systems.
7
//
8
// This program is free software; you can redistribute it and/or
9
// modify it under the terms of the GNU General Public License
10
// as published by the Free Software Foundation; either version 2
11
// of the License, or (at your option) any later version.
12

13
#include "simulation.h"
14

15
#include <algorithm>
16
#include <cstddef>
17

18
#include <celutil/strnatcmp.h>
19
#include "body.h"
20
#include "location.h"
21
#include "render.h"
22

23

24
Simulation::Simulation(Universe* _universe) :
25
    universe(_universe)
26
{
27
    activeObserver = new Observer();
28
    observers.push_back(activeObserver);
29
}
30

31

32
Simulation::~Simulation()
33
{
34
    for (const auto observer : observers)
35
        delete observer;
36
}
37

38

39
static const Star* getSun(const Body* body)
40
{
41
    const PlanetarySystem* system = body->getSystem();
42
    return system ? system->getStar() : nullptr;
43
}
44

45

46
void Simulation::render(Renderer& renderer)
47
{
48
    renderer.render(*activeObserver,
49
                    *universe,
50
                    faintestVisible,
51
                    selection);
52
}
53

54

55
void Simulation::render(Renderer& renderer, Observer& observer)
56
{
57
    renderer.render(observer,
58
                    *universe,
59
                    faintestVisible,
60
                    selection);
61
}
62

63

64
Universe* Simulation::getUniverse() const
65
{
66
    return universe;
67
}
68

69

70
// Get the time (Julian date)
71
double Simulation::getTime() const
72
{
73
    return activeObserver->getTime();
74
}
75

76
// Set the time to the specified Julian date
77
void Simulation::setTime(double jd)
78
{
79
    if (syncTime)
80
    {
81
        for (const auto observer : observers)
82
        {
83
            observer->setTime(jd);
84
        }
85
    }
86
    else
87
    {
88
        activeObserver->setTime(jd);
89
    }
90
}
91

92

93
// Get the clock time elapsed since the object was created
94
double Simulation::getRealTime() const
95
{
96
    return realTime;
97
}
98

99

100
double Simulation::getArrivalTime() const
101
{
102
    return activeObserver->getArrivalTime();
103
}
104

105

106
// Tick the simulation by dt seconds
107
void Simulation::update(double dt)
108
{
109
    realTime += dt;
110

111
    for (const auto observer : observers)
112
    {
113
        observer->update(dt, timeScale);
114
    }
115

116
    // Reset nearest solar system
117
    closestSolarSystem = std::nullopt;
118
}
119

120

121
Selection Simulation::getSelection() const
122
{
123
    return selection;
124
}
125

126

127
void Simulation::setSelection(const Selection& sel)
128
{
129
    selection = sel;
130
}
131

132

133
Selection Simulation::getTrackedObject() const
134
{
135
    return activeObserver->getTrackedObject();
136
}
137

138

139
void Simulation::setTrackedObject(const Selection& sel)
140
{
141
    activeObserver->setTrackedObject(sel);
142
}
143

144

145
Selection Simulation::pickObject(const Eigen::Vector3f& pickRay,
146
                                 std::uint64_t renderFlags,
147
                                 float tolerance)
148
{
149
    return universe->pick(activeObserver->getPosition(),
150
                          activeObserver->getOrientationf().conjugate() * pickRay,
151
                          activeObserver->getTime(),
152
                          renderFlags,
153
                          faintestVisible,
154
                          tolerance);
155
}
156

157
void Simulation::reverseObserverOrientation()
158
{
159
    activeObserver->reverseOrientation();
160
}
161

162

163
Observer& Simulation::getObserver()
164
{
165
    return *activeObserver;
166
}
167

168

169
const Observer& Simulation::getObserver() const
170
{
171
    return *activeObserver;
172
}
173

174

175
Observer* Simulation::duplicateActiveObserver()
176
{
177
    return observers.emplace_back(new Observer(*getActiveObserver()));
178
}
179

180

181
void Simulation::removeObserver(Observer* o)
182
{
183
    auto iter = std::find(observers.begin(), observers.end(), o);
184
    if (iter != observers.end())
185
        observers.erase(iter);
186
}
187

188

189
Observer* Simulation::getActiveObserver()
190
{
191
    return activeObserver;
192
}
193

194

195
const Observer* Simulation::getActiveObserver() const
196
{
197
    return activeObserver;
198
}
199

200

201
void Simulation::setActiveObserver(Observer* o)
202
{
203
    auto iter = std::find(observers.begin(), observers.end(), o);
204
    if (iter != observers.end())
205
        activeObserver = o;
206
}
207

208

209
void Simulation::setObserverPosition(const UniversalCoord& pos)
210
{
211
    activeObserver->setPosition(pos);
212
}
213

214
void Simulation::setObserverOrientation(const Eigen::Quaternionf& orientation)
215
{
216
    activeObserver->setOrientation(orientation);
217
}
218

219

220
Observer::ObserverMode Simulation::getObserverMode() const
221
{
222
    return activeObserver->getMode();
223
}
224

225
void Simulation::setObserverMode(Observer::ObserverMode mode)
226
{
227
    activeObserver->setMode(mode);
228
}
229

230
void Simulation::setFrame(ObserverFrame::CoordinateSystem coordSys,
231
                          const Selection& refObject,
232
                          const Selection& targetObject)
233
{
234
    activeObserver->setFrame(coordSys, refObject, targetObject);
235
}
236

237
void Simulation::setFrame(ObserverFrame::CoordinateSystem coordSys,
238
                          const Selection& refObject)
239
{
240
    activeObserver->setFrame(coordSys, refObject);
241
}
242

243
const ObserverFrame::SharedConstPtr& Simulation::getFrame() const
244
{
245
    return activeObserver->getFrame();
246
}
247

248
// Rotate the observer about its center.
249
void Simulation::rotate(const Eigen::Quaternionf& q)
250
{
251
    activeObserver->rotate(q);
252
}
253

254
// Orbit around the selection (if there is one.)  This involves changing
255
// both the observer's position and orientation.
256
void Simulation::orbit(const Eigen::Quaternionf& q)
257
{
258
    activeObserver->orbit(selection, q);
259
}
260

261
// Orbit around the selection (if there is one.)  This involves changing
262
// both the observer's position and orientation.
263
bool Simulation::orbit(const Eigen::Vector3f& from, const Eigen::Vector3f& to)
264
{
265
    return activeObserver->orbit(selection, from, to);
266
}
267

268
// Exponential camera dolly--move toward or away from the selected object
269
// at a rate dependent on the observer's distance from the object.
270
void Simulation::changeOrbitDistance(float d)
271
{
272
    activeObserver->changeOrbitDistance(selection, d);
273
}
274

275
void Simulation::scaleOrbitDistance(float scale, const std::optional<Eigen::Vector3f>& focus)
276
{
277
    activeObserver->scaleOrbitDistance(selection, scale, focus);
278
}
279

280
void Simulation::setTargetSpeed(float s)
281
{
282
    activeObserver->setTargetSpeed(s);
283
}
284

285
float Simulation::getTargetSpeed() const
286
{
287
    return activeObserver->getTargetSpeed();
288
}
289

290
void Simulation::gotoSelection(double gotoTime,
291
                               const Eigen::Vector3f& up,
292
                               ObserverFrame::CoordinateSystem upFrame)
293
{
294
    if (selection.getType() == SelectionType::Location)
295
    {
296
        activeObserver->gotoSelectionGC(selection,
297
                                        gotoTime,
298
                                        up, upFrame);
299
    }
300
    else
301
    {
302
        activeObserver->gotoSelection(selection, gotoTime, up, upFrame);
303
    }
304
}
305

306
void Simulation::gotoSelection(double gotoTime,
307
                               double distance,
308
                               const Eigen::Vector3f& up,
309
                               ObserverFrame::CoordinateSystem upCoordSys)
310
{
311
    activeObserver->gotoSelection(selection, gotoTime, distance, up, upCoordSys);
312
}
313

314
void Simulation::gotoSelectionLongLat(double gotoTime,
315
                                      double distance,
316
                                      float longitude,
317
                                      float latitude,
318
                                      const Eigen::Vector3f& up)
319
{
320
    activeObserver->gotoSelectionLongLat(selection, gotoTime, distance,
321
                                         longitude, latitude, up);
322
}
323

324

325
void Simulation::gotoLocation(const UniversalCoord& position,
326
                              const Eigen::Quaterniond& orientation,
327
                              double duration)
328
{
329
    activeObserver->gotoLocation(position, orientation, duration);
330
}
331

332

333
void Simulation::getSelectionLongLat(double& distance,
334
                                     double& longitude,
335
                                     double& latitude)
336
{
337
    activeObserver->getSelectionLongLat(selection, distance, longitude, latitude);
338
}
339

340

341
void Simulation::gotoSurface(double duration)
342
{
343
    activeObserver->gotoSurface(selection, duration);
344
}
345

346

347
void Simulation::cancelMotion()
348
{
349
    activeObserver->cancelMotion();
350
}
351

352
void Simulation::centerSelection(double centerTime)
353
{
354
    activeObserver->centerSelection(selection, centerTime);
355
}
356

357
void Simulation::centerSelectionCO(double centerTime)
358
{
359
    activeObserver->centerSelectionCO(selection, centerTime);
360
}
361

362
void Simulation::follow()
363
{
364
    activeObserver->follow(selection);
365
}
366

367
void Simulation::geosynchronousFollow()
368
{
369
    activeObserver->geosynchronousFollow(selection);
370
}
371

372
void Simulation::phaseLock()
373
{
374
    activeObserver->phaseLock(selection);
375
}
376

377
void Simulation::chase()
378
{
379
    activeObserver->chase(selection);
380
}
381

382

383
// Choose a planet around a star given it's index in the planetary system.
384
// The planetary system is either the system of the selected object, or the
385
// nearest planetary system if no object is selected.  If index is less than
386
// zero, pick the star.  This function should probably be in celestiacore.cpp.
387
void Simulation::selectPlanet(int index)
388
{
389
    if (index < 0)
390
    {
391
        if (selection.getType() == SelectionType::Body)
392
        {
393
            PlanetarySystem* system = selection.body()->getSystem();
394
            if (system != nullptr)
395
                setSelection(system->getStar());
396
        }
397
    }
398
    else
399
    {
400
        const Star* star = nullptr;
401
        if (selection.getType() == SelectionType::Star)
402
            star = selection.star();
403
        else if (selection.getType() == SelectionType::Body)
404
            star = getSun(selection.body());
405

406
        SolarSystem* solarSystem = nullptr;
407
        if (star != nullptr)
408
            solarSystem = universe->getSolarSystem(star);
409
        else
410
            solarSystem = getNearestSolarSystem();
411

412
        if (solarSystem != nullptr &&
413
            index < solarSystem->getPlanets()->getSystemSize())
414
        {
415
            setSelection(Selection(solarSystem->getPlanets()->getBody(index)));
416
        }
417
    }
418
}
419

420

421
// Select an object by name, with the following priority:
422
//   1. Try to look up the name in the star database
423
//   2. Search the deep sky catalog for a matching name.
424
//   3. Search the planets and moons in the planetary system of the currently selected
425
//      star
426
//   4. Search the planets and moons in any 'nearby' (< 0.1 ly) planetary systems
427
Selection Simulation::findObject(std::string_view s, bool i18n) const
428
{
429
    Selection path[2];
430
    std::size_t nPathEntries = 0;
431

432
    if (!selection.empty())
433
        path[nPathEntries++] = selection;
434

435
    if (auto nearestSolarSystem = getNearestSolarSystem(); nearestSolarSystem != nullptr)
436
        path[nPathEntries++] = Selection(nearestSolarSystem->getStar());
437

438
    return universe->find(s, {path, nPathEntries}, i18n);
439
}
440

441

442
// Find an object from a path, for example Sol/Earth/Moon or Upsilon And/b
443
// Currently, 'absolute' paths starting with a / are not supported nor are
444
// paths that contain galaxies.
445
Selection Simulation::findObjectFromPath(std::string_view s, bool i18n) const
446
{
447
    Selection path[2];
448
    std::size_t nPathEntries = 0;
449

450
    if (!selection.empty())
451
        path[nPathEntries++] = selection;
452

453
    if (auto nearestSolarSystem = getNearestSolarSystem(); nearestSolarSystem != nullptr)
454
        path[nPathEntries++] = Selection(nearestSolarSystem->getStar());
455

456
    return universe->findPath(s, {path, nPathEntries}, i18n);
457
}
458

459

460
void Simulation::getObjectCompletion(std::vector<std::string>& completion,
461
                                     std::string_view s,
462
                                     bool withLocations) const
463
{
464
    Selection path[2];
465
    std::size_t nPathEntries = 0;
466

467
    if (!selection.empty())
468
    {
469
        if (selection.getType() == SelectionType::Location)
470
        {
471
            path[nPathEntries++] = Selection(selection.location()->getParentBody());
472
        }
473
        else
474
        {
475
            path[nPathEntries++] = selection;
476
        }
477
    }
478

479
    if (auto nearestSolarSystem = getNearestSolarSystem();
480
        nearestSolarSystem != nullptr && nearestSolarSystem != universe->getSolarSystem(selection))
481
    {
482
        path[nPathEntries++] = Selection(nearestSolarSystem->getStar());
483
    }
484

485
    universe->getCompletionPath(completion, s, {path, nPathEntries}, withLocations);
486

487
    std::sort(completion.begin(), completion.end(),
488
              [](const std::string &s1, const std::string &s2) { return strnatcmp(s1, s2) < 0; });
489
}
490

491

492
double Simulation::getTimeScale() const
493
{
494
    return pauseState?storedTimeScale:timeScale;
495
}
496

497
void Simulation::setTimeScale(double _timeScale)
498
{
499
    if (pauseState)
500
    {
501
        storedTimeScale = _timeScale;
502
    }
503
    else
504
    {
505
        timeScale = _timeScale;
506
    }
507
}
508

509
bool Simulation::getSyncTime() const
510
{
511
    return syncTime;
512
}
513

514
void Simulation::setSyncTime(bool sync)
515
{
516
    syncTime = sync;
517
}
518

519
bool Simulation::getPauseState() const
520
{
521
    return pauseState;
522
}
523

524
void Simulation::setPauseState(bool state)
525
{
526
    if (pauseState == state) return;
527

528
    pauseState = state;
529
    if (pauseState)
530
    {
531
        storedTimeScale = timeScale;
532
        timeScale = 0.0;
533
    }
534
    else
535
    {
536
        timeScale = storedTimeScale;
537
    }
538
}
539

540
// Synchronize all observers to active observer time
541
void Simulation::synchronizeTime()
542
{
543
    for (const auto observer : observers)
544
    {
545
        observer->setTime(activeObserver->getTime());
546
    }
547
}
548

549

550
float Simulation::getFaintestVisible() const
551
{
552
    return faintestVisible;
553
}
554

555

556
void Simulation::setFaintestVisible(float magnitude)
557
{
558
    faintestVisible = magnitude;
559
}
560

561

562
SolarSystem* Simulation::getNearestSolarSystem() const
563
{
564
    if (!closestSolarSystem.has_value())
565
        closestSolarSystem = universe->getNearestSolarSystem(activeObserver->getPosition());
566
    return *closestSolarSystem;
567
}
568

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

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

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

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