Cogs.Core
ClipmapGeometry.cpp
1#include "ClipmapGeometry.h"
2
3#include "ClipmapTerrainTypes.h"
4
5Cogs::ClipmapMesh Cogs::createMesh(IBuffers * buffers, double left, double bottom, double right, double top, size_t numberOfPartitionsX, size_t numberOfPartitionsY, const VertexFormatHandle & vertexFormat)
6{
7 size_t numberOfPositions = (numberOfPartitionsX + 1) * (numberOfPartitionsY + 1);
8 size_t numberOfIndices = (numberOfPartitionsX * numberOfPartitionsY) * 6;
9
10 Vector2d lowerLeft(left, bottom);
11 Vector2d toUpperRight = Vector2d(right, top) - lowerLeft;
12
13 std::vector<Vector2> positions(numberOfPositions);
14 std::vector<unsigned short> indexes(numberOfIndices);
15
16 for (size_t y = 0; y <= numberOfPartitionsY; ++y) {
17 double deltaY = y / (double)numberOfPartitionsY;
18 double currentY = lowerLeft[1] + (deltaY * toUpperRight[1]);
19
20 for (size_t x = 0; x <= numberOfPartitionsX; ++x) {
21 double deltaX = x / (double)numberOfPartitionsX;
22 double currentX = lowerLeft[0] + (deltaX * toUpperRight[0]);
23
24 positions[y * (numberOfPartitionsX + 1) + x] = Vector2((float)currentX, (float)currentY);
25 }
26 }
27
28 size_t rowDelta = numberOfPartitionsX + 1;
29 size_t i = 0;
30 size_t index = 0;
31
32 for (size_t y = 0; y < numberOfPartitionsY; ++y) {
33 for (size_t x = 0; x < numberOfPartitionsX; ++x) {
34 indexes[index++] = static_cast<unsigned short>(i);
35 indexes[index++] = static_cast<unsigned short>(i + 1);
36 indexes[index++] = static_cast<unsigned short>(rowDelta + (i + 1));
37
38 indexes[index++] = static_cast<unsigned short>(i);
39 indexes[index++] = static_cast<unsigned short>(rowDelta + (i + 1));
40 indexes[index++] = static_cast<unsigned short>(rowDelta + i);
41
42 i += 1;
43 }
44
45 i += 1;
46 }
47
48 ClipmapMesh mesh = {
49 buffers->loadVertexBuffer(positions.data(), positions.size(), vertexFormat),
50 buffers->loadIndexBuffer(indexes.data(), indexes.size(), sizeof(unsigned short)),
51 static_cast<uint32_t>(getSize(vertexFormat)),
52 static_cast<int>(right - left),
53 static_cast<int>(top - bottom),
54 };
55
56 return mesh;
57}
58
59Cogs::ClipmapMesh Cogs::createSimpleMesh(IBuffers * buffers, double left, double bottom, double right, double top, size_t numberOfPartitionsX, size_t numberOfPartitionsY, const VertexFormatHandle & vertexFormat)
60{
61 size_t numberOfPositions = 1 + (numberOfPartitionsX + 1) * 2 + (numberOfPartitionsY - 1) * 2;
62 size_t numberOfIndices = numberOfPositions * 3;
63
64 Vector2d lowerLeft(left, bottom);
65 Vector2d toUpperRight = Vector2d(right, top) - lowerLeft;
66
67 std::vector<Vector2> positions(numberOfPositions);
68 std::vector<unsigned short> indexes(numberOfIndices);
69
70 // Center vertex.
71 int index = 0;
72 positions[index++] = Vector2(lowerLeft + toUpperRight * 0.5);
73
74 for (size_t i = 0; i < numberOfPartitionsX + 1; ++i) {
75 positions[index++] = Vector2(lowerLeft + Vector2d(toUpperRight.x * (1.0 / (double)numberOfPartitionsX) * (double)i, 0));
76 }
77
78 for (size_t i = 1; i < numberOfPartitionsY; ++i) {
79 positions[index++] = Vector2(lowerLeft + Vector2d(toUpperRight.x, toUpperRight.y * (1.0 / (double)numberOfPartitionsY) * (double)i));
80 }
81
82 for (int i = static_cast<int>(numberOfPartitionsX); i >= 0; --i) {
83 positions[index++] = Vector2(lowerLeft + Vector2d(toUpperRight.x * (1.0 / (double)numberOfPartitionsX) * (double)i, toUpperRight.y));
84 }
85
86 for (int i = static_cast<int>(numberOfPartitionsY) - 1; i > 0; --i) {
87 positions[index++] = Vector2(lowerLeft + Vector2d(0, toUpperRight.y * (1.0 / (double)numberOfPartitionsX) * (double)i));
88 }
89
90 index = 0;
91 for (size_t i = 1; i < numberOfPositions; ++i) {
92 indexes[index++] = static_cast<unsigned short>(0);
93 indexes[index++] = static_cast<unsigned short>(i);
94 indexes[index++] = static_cast<unsigned short>(i + 1);
95 }
96
97 ClipmapMesh mesh = {
98 buffers->loadVertexBuffer(positions.data(), positions.size(), vertexFormat),
99 buffers->loadIndexBuffer(indexes.data(), indexes.size(), sizeof(unsigned short)),
100 static_cast<uint32_t>(getSize(vertexFormat)),
101 static_cast<int>(right - left),
102 static_cast<int>(top - bottom),
103 };
104
105 return mesh;
106}
107
108Cogs::ClipmapMesh Cogs::createDegenerateMesh(IBuffers * buffers, size_t clipmapSegments, size_t clipmapPosts, const VertexFormatHandle & vertexFormat)
109{
110 size_t numberOfPositions = clipmapSegments * 4;
111 size_t numberOfIndices = (clipmapSegments / 2) * 3 * 4;
112
113 std::vector<Vector2> positions(numberOfPositions);
114 std::vector<unsigned short> indexes;
115
116 size_t index = 0;
117
118 for (size_t i = 0; i < clipmapPosts; ++i) {
119 positions[index++] = Vector2(0, (float)i);
120 }
121
122 for (size_t i = 1; i < clipmapPosts; ++i) {
123 positions[index++] = Vector2((float)i, (float)clipmapSegments);
124 }
125
126 for (int i = static_cast<int>(clipmapSegments - 1); i >= 0; --i) {
127 positions[index++] = Vector2((float)clipmapSegments, (float)i);
128 }
129
130 for (size_t i = clipmapSegments - 1; i > 0; --i) {
131 positions[index++] = Vector2((float)i, 0);
132 }
133
134 assert(index == positions.size());
135
136 for (size_t i = 0; i < numberOfIndices; i += 2) {
137 indexes.push_back(static_cast<unsigned short>(i));
138 indexes.push_back(static_cast<unsigned short>(i + 1));
139 indexes.push_back(static_cast<unsigned short>(i + 2));
140 }
141
142 ClipmapMesh mesh = {
143 buffers->loadVertexBuffer(positions.data(), positions.size(), vertexFormat),
144 buffers->loadIndexBuffer(indexes.data(), indexes.size(), sizeof(unsigned short)),
145 static_cast<uint32_t>(getSize(vertexFormat)),
146 -1,
147 -1,
148 };
149
150 return mesh;
151}
152
153void Cogs::initializeGeometry(ClipmapGeometry & clipmapGeometry, IBuffers * buffers, size_t fillPatchPosts, size_t fillPatchSegments, size_t clipmapSegments, size_t clipmapPosts)
154{
155 VertexElement element = { 0, DataFormat::X32Y32_FLOAT, ElementSemantic::Position, 0, InputType::VertexData, 0 };
156 clipmapGeometry.meshFormat = buffers->createVertexFormat(&element, 1);
157 clipmapGeometry.stride = getSize(clipmapGeometry.meshFormat);
158
159 clipmapGeometry.buffers = buffers;
160 clipmapGeometry.worldMesh.vertexBuffer = VertexBufferHandle::InvalidHandle;
161 clipmapGeometry.simpleWorldMesh.vertexBuffer = VertexBufferHandle::InvalidHandle;
162
163 double segments = static_cast<double>(fillPatchSegments);
164 double posts = static_cast<double>(fillPatchPosts);
165
166 // Create the MxM block used to fill the ring and the field.
167 clipmapGeometry.fieldBlockMesh = createMesh(buffers, 0.0, 0.0, segments, segments, fillPatchSegments, fillPatchSegments, clipmapGeometry.meshFormat);
168
169 // Create the Mx3 block used to fill the space between the MxM blocks in the ring
170 clipmapGeometry.ringFixupHorizontalMesh = createMesh(buffers, 0.0, 0.0, segments, 2.0, fillPatchSegments, 2, clipmapGeometry.meshFormat);
171
172 // Create the 3xM block used to fill the space between the MxM blocks in the ring
173 clipmapGeometry.ringFixupVerticalMesh = createMesh(buffers, 0.0, 0.0, 2.0, segments, 2, fillPatchSegments, clipmapGeometry.meshFormat);
174
175 clipmapGeometry.offsetStripHorizontalMesh = createMesh(buffers, 0.0, 0.0, 2.0 * posts, 1.0, 2 * fillPatchPosts, 1, clipmapGeometry.meshFormat);
176 clipmapGeometry.offsetStripVerticalMesh = createMesh(buffers, 0.0, 0.0, 1.0, 2.0 * posts - 1.0, 1, 2 * fillPatchPosts - 1, clipmapGeometry.meshFormat);
177
178 clipmapGeometry.centerMesh = createMesh(buffers, 0, 0, 2.0, 2.0, 2, 2, clipmapGeometry.meshFormat);
179
180 clipmapGeometry.degenerateTriangleMesh = createDegenerateMesh(buffers, clipmapSegments, clipmapPosts, clipmapGeometry.meshFormat);
181
182 clipmapGeometry.simpleMesh = createSimpleMesh(buffers, 0, 0, segments, segments, fillPatchSegments, fillPatchSegments, clipmapGeometry.meshFormat);
183
184 clipmapGeometry.initialized = true;
185}
186
187void Cogs::releaseMesh(ClipmapMesh & mesh, IBuffers * buffers)
188{
189 buffers->releaseVertexBuffer(mesh.vertexBuffer);
190 buffers->releaseIndexBuffer(mesh.indexBuffer);
191}
192
193void Cogs::releaseGeometry(ClipmapGeometry & clipmapGeometry, IBuffers * buffers)
194{
195 releaseMesh(clipmapGeometry.fieldBlockMesh, buffers);
196
197 releaseMesh(clipmapGeometry.ringFixupHorizontalMesh, buffers);
198 releaseMesh(clipmapGeometry.ringFixupVerticalMesh, buffers);
199
200 releaseMesh(clipmapGeometry.offsetStripHorizontalMesh, buffers);
201 releaseMesh(clipmapGeometry.offsetStripVerticalMesh, buffers);
202
203 releaseMesh(clipmapGeometry.centerMesh, buffers);
204
205 releaseMesh(clipmapGeometry.degenerateTriangleMesh, buffers);
206
207 clipmapGeometry.initialized = false;
208}