Celestia

Форк
0
/
mapmanager.cpp 
193 строки · 5.1 Кб
1
//
2
// mapmanager.cpp
3
//
4
// Copyright © 2020 Celestia Development Team. All rights reserved.
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 "mapmanager.h"
12

13
#include <array>
14
#include <cmath>
15
#include <cstring>
16
#include <fstream>
17
#include <string_view>
18

19
#include <celutil/fsutils.h>
20
#include <celutil/logger.h>
21

22
using namespace std::string_view_literals;
23
using celestia::util::GetLogger;
24

25
namespace
26
{
27

28
constexpr std::array extensions = {"map"sv};
29

30
}
31

32
WarpMesh::WarpMesh(int nx, int ny, float *data) :
33
    nx(nx),
34
    ny(ny),
35
    data(data)
36
{
37
}
38

39
WarpMesh::~WarpMesh()
40
{
41
    delete data;
42
}
43

44
std::vector<float> WarpMesh::scopedDataForRendering() const
45
{
46
    int step = 5 * 6;
47
    int size = (nx - 1) * (ny - 1) * step;
48
    std::vector<float> renderingData(static_cast<std::size_t>(size));
49
    for (int y = 0; y < ny - 1; y += 1)
50
    {
51
        for (int x = 0; x < nx - 1; x += 1)
52
        {
53
            float *destination = renderingData.data() + (y * (nx - 1) + x) * step;
54
            const float *source = &data[(y * nx + x) * 5];
55
            // Top left triangle
56
            std::memcpy(destination, source + 5 * nx, sizeof(float) * 5);
57
            std::memcpy(destination + 5, source, sizeof(float) * 5);
58
            std::memcpy(destination + 10, source + 5, sizeof(float) * 5);
59
            // Bottom right triangle
60
            std::memcpy(destination + 15, source + 5 * nx, sizeof(float) * 5);
61
            std::memcpy(destination + 20, source + 5, sizeof(float) * 5);
62
            std::memcpy(destination + 25, source + 5 * nx + 5, sizeof(float) * 5);
63
        }
64
    }
65
    return renderingData;
66
}
67

68
int WarpMesh::count() const
69
{
70
    return 6 * (nx - 1) * (ny - 1);
71
}
72

73
bool WarpMesh::mapVertex(float x, float y, float* u, float* v) const
74
{
75
    float minX = data[0];
76
    float minY = data[1];
77
    float maxX = data[(nx * ny - 1) * 5];
78
    float maxY = data[(nx * ny - 1) * 5 + 1];
79

80
    float stepX = (maxX - minX) / (nx - 1);
81
    float stepY = (maxY - minY) / (ny - 1);
82

83
    float locX = (x - minX) / stepX;
84
    float locY = (y - minY) / stepY;
85
    auto floX = static_cast<int>(std::floor(locX));
86
    auto floY = static_cast<int>(std::floor(locY));
87
    locX -= floX;
88
    locY -= floY;
89

90
    if (floX < 0 || floX >= nx - 1 || floY < 0 || floY >= ny - 1)
91
        return false;
92

93
    float p1x = data[(floY * nx + floX) * 5 + 2];
94
    float p1y = data[(floY * nx + floX) * 5 + 3];
95
    float p2x = data[(floY * nx + floX + 1) * 5 + 2];
96
    float p2y = data[(floY * nx + floX + 1) * 5 + 3];
97
    float p3x = data[(floY * nx + floX + nx) * 5 + 2];
98
    float p3y = data[(floY * nx + floX + nx) * 5 + 3];
99
    float p4x = data[(floY * nx + floX + nx + 1) * 5 + 2];
100
    float p4y = data[(floY * nx + floX + nx + 1) * 5 + 3];
101

102
    if (locX + locY <= 1)
103
    {
104
        // the top left part triangle
105
        *u = p1x + locX * (p2x - p1x) + locY * (p3x - p1x);
106
        *v = p1y + locX * (p2y - p1y) + locY * (p3y - p1y);
107
    }
108
    else
109
    {
110
        // the bottom right triangle
111
        locX -= 1;
112
        locY -= 1;
113
        *u = p4x + locX * (p4x - p3x) + locY * (p4x - p2x);
114
        *v = p4y + locX * (p4y - p3y) + locY * (p4y - p2y);
115
    }
116
    // Texture coordinate is [0, 1], normalize to [-1, 1]
117
    *u = (*u) * 2 - 1;
118
    *v = (*v) * 2 - 1;
119
    return true;
120
}
121

122
WarpMeshManager* GetWarpMeshManager()
123
{
124
    static WarpMeshManager* const warpMeshManager = std::make_unique<WarpMeshManager>("warp").release(); //NOSONAR
125
    return warpMeshManager;
126
}
127

128
fs::path WarpMeshInfo::resolve(const fs::path& baseDir) const
129
{
130
    bool wildcard = source.extension() == ".*";
131

132
    fs::path filename = baseDir / source;
133

134
    if (wildcard)
135
    {
136
        fs::path matched = celestia::util::ResolveWildcard(filename, extensions);
137
        if (!matched.empty())
138
            return matched;
139
    }
140

141
    return filename;
142
}
143

144

145
std::unique_ptr<WarpMesh> WarpMeshInfo::load(const fs::path& name) const
146
{
147
#define MESHTYPE_RECT 2
148
    std::ifstream f(name);
149
    if (!f.good())
150
        return nullptr;
151

152
    int type, nx, ny;
153
    if (!(f >> type))
154
    {
155
        GetLogger()->error("Failed to read mesh header\n");
156
        return nullptr;
157
    }
158

159
    if (type != MESHTYPE_RECT)
160
    {
161
        GetLogger()->error("Unsupported mesh type found: {}\n", type);
162
        return nullptr;
163
    }
164

165
    if (!(f >> nx >> ny))
166
    {
167
        GetLogger()->error("Failed to read mesh header\n");
168
        return nullptr;
169
    }
170

171
    if (nx < 2 || ny < 2)
172
    {
173
        GetLogger()->error("Row and column numbers should be larger than 2\n");
174
        return nullptr;
175
    }
176

177
    float *data = new float[nx * ny * 5];
178
    for (int y = 0; y < ny; y += 1)
179
    {
180
        for (int x = 0; x < nx; x += 1)
181
        {
182
            float *base = &data[(y * nx + x) * 5];
183
            if (!(f >> base[0] >> base[1] >> base[2] >> base[3] >> base[4]))
184
            {
185
                GetLogger()->error("Failed to read mesh data\n");
186
                delete[] data;
187
                return nullptr;
188
            }
189
        }
190
    }
191
    GetLogger()->info("Read a mesh of {} x {}\n", nx, ny);
192
    return std::make_unique<WarpMesh>(nx, ny, data);
193
}
194

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

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

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

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