History

Merging

samcake committed 11 years ago

Commit 910038c2 parents 21f53f1 7b5cbbf46 files · +2342 −1034Browse files

Showing the changes to libraries/render-utils/src/GeometryCache.cpp (1 of 46 files). Show all

Unified · Split

libraries/render-utils/src/GeometryCache.cpp+486−460
@@ -35,269 +35,537 @@ · 34 unmodified lines
35 35
36const int GeometryCache::UNKNOWN_ID = -1;36const int GeometryCache::UNKNOWN_ID = -1;
37 37
38GeometryCache::GeometryCache() :
39 _nextID(0)
40{
41}
42 38
43GeometryCache::~GeometryCache() {39static const uint FLOATS_PER_VERTEX = 3;
44 #ifdef WANT_DEBUG40static const uint VERTICES_PER_TRIANGLE = 3;
45 qCDebug(renderutils) << "GeometryCache::~GeometryCache()... ";41static const uint TRIANGLES_PER_QUAD = 2;
46 qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size();42static const uint CUBE_FACES = 6;
47 qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size();43static const uint CUBE_VERTICES_PER_FACE = 4;
48 qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;44static const uint CUBE_VERTICES = CUBE_FACES * CUBE_VERTICES_PER_FACE;
49 #endif //def WANT_DEBUG45static const uint CUBE_VERTEX_POINTS = CUBE_VERTICES * FLOATS_PER_VERTEX;
46static const uint CUBE_INDICES = CUBE_FACES * TRIANGLES_PER_QUAD * VERTICES_PER_TRIANGLE;
47static const uint SPHERE_LATITUDES = 24;
48static const uint SPHERE_MERIDIANS = SPHERE_LATITUDES * 2;
49static const uint SPHERE_INDICES = SPHERE_MERIDIANS * (SPHERE_LATITUDES - 1) * TRIANGLES_PER_QUAD * VERTICES_PER_TRIANGLE;
50
51static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
52static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
53static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
54static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
55
56static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
57static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
58
59static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
60static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
61
62
63void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const VertexVector& vertices) {
64 vertexBuffer->append(vertices);
65
66 _positionView = gpu::BufferView(vertexBuffer, 0,
67 vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);
68 _normalView = gpu::BufferView(vertexBuffer, SHAPE_NORMALS_OFFSET,
69 vertexBuffer->getSize(), SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);
50}70}
51 71
52const int NUM_VERTICES_PER_TRIANGLE = 3;72void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const IndexVector& indices, const IndexVector& wireIndices) {
53const int NUM_TRIANGLES_PER_QUAD = 2;73 _indices = indexBuffer;
54const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;74 if (!indices.empty()) {
55const int NUM_COORDS_PER_VERTEX = 3;75 _indexOffset = indexBuffer->getSize();
56 76 _indexCount = indices.size();
57void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {77 indexBuffer->append(indices);
58 bool registered = (id != UNKNOWN_ID);78 }
59
60 Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0));
61 IntPair slicesStacksKey(slices, stacks);
62 Vec3Pair colorKey(glm::vec3(color.x, color.y, slices), glm::vec3(color.z, color.w, stacks));
63
64 int vertices = slices * (stacks - 1) + 2;
65 int indices = slices * (stacks - 1) * NUM_VERTICES_PER_TRIANGULATED_QUAD;
66 79
67 if ((registered && (!_registeredSphereVertices.contains(id) || _lastRegisteredSphereVertices[id] != radiusKey))80 if (!wireIndices.empty()) {
68 || (!registered && !_sphereVertices.contains(radiusKey))) {81 _wireIndexOffset = indexBuffer->getSize();
82 _wireIndexCount = wireIndices.size();
83 indexBuffer->append(wireIndices);
84 }
85}
69 86
70 if (registered && _registeredSphereVertices.contains(id)) {87void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
71 _registeredSphereVertices[id].reset();88 batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
72 #ifdef WANT_DEBUG89 batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
73 qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED VERTICES BUFFER";90}
74 #endif
75 }
76 91
77 auto verticesBuffer = std::make_shared<gpu::Buffer>();92void GeometryCache::ShapeData::draw(gpu::Batch& batch) const {
78 if (registered) {93 if (_indexCount) {
79 _registeredSphereVertices[id] = verticesBuffer;94 setupBatch(batch);
80 _lastRegisteredSphereVertices[id] = radiusKey;95 batch.setIndexBuffer(gpu::UINT16, _indices, _indexOffset);
81 } else {96 batch.drawIndexed(gpu::TRIANGLES, _indexCount);
82 _sphereVertices[radiusKey] = verticesBuffer;97 }
83 }98}
84 99
85 GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];100void GeometryCache::ShapeData::drawWire(gpu::Batch& batch) const {
86 GLfloat* vertex = vertexData;101 if (_wireIndexCount) {
102 setupBatch(batch);
103 batch.setIndexBuffer(gpu::UINT16, _indices, _wireIndexOffset);
104 batch.drawIndexed(gpu::LINES, _wireIndexCount);
105 }
106}
87 107
88 // south pole108void GeometryCache::ShapeData::drawInstances(gpu::Batch& batch, size_t count) const {
89 *(vertex++) = 0.0f;109 if (_indexCount) {
90 *(vertex++) = 0.0f;110 setupBatch(batch);
91 *(vertex++) = -1.0f * radius;111 batch.setIndexBuffer(gpu::UINT16, _indices, _indexOffset);
112 batch.drawIndexedInstanced(count, gpu::TRIANGLES, _indexCount);
113 }
114}
92 115
93 //add stacks vertices climbing up Y axis116void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count) const {
94 for (int i = 1; i < stacks; i++) {117 if (_wireIndexCount) {
95 float phi = PI * (float)i / (float)(stacks) - PI_OVER_TWO;118 setupBatch(batch);
96 float z = sinf(phi) * radius;119 batch.setIndexBuffer(gpu::UINT16, _indices, _wireIndexOffset);
97 float stackRadius = cosf(phi) * radius;120 batch.drawIndexedInstanced(count, gpu::LINES, _wireIndexCount);
98 121 }
99 for (int j = 0; j < slices; j++) {122}
100 float theta = TWO_PI * (float)j / (float)slices;
101 123
102 *(vertex++) = sinf(theta) * stackRadius;124const VertexVector& icosahedronVertices() {
103 *(vertex++) = cosf(theta) * stackRadius;125 static const float phi = (1.0 + sqrt(5.0)) / 2.0;
104 *(vertex++) = z;126 static const float a = 0.5;
105 }127 static const float b = 1.0 / (2.0 * phi);
106 }128
129 static const VertexVector vertices{ //
130 vec3(0, b, -a), vec3(-b, a, 0), vec3(b, a, 0), //
131 vec3(0, b, a), vec3(b, a, 0), vec3(-b, a, 0), //
132 vec3(0, b, a), vec3(-a, 0, b), vec3(0, -b, a), //
133 vec3(0, b, a), vec3(0, -b, a), vec3(a, 0, b), //
134 vec3(0, b, -a), vec3(a, 0, -b), vec3(0, -b, -a),//
135 vec3(0, b, -a), vec3(0, -b, -a), vec3(-a, 0, -b), //
136 vec3(0, -b, a), vec3(-b, -a, 0), vec3(b, -a, 0), //
137 vec3(0, -b, -a), vec3(b, -a, 0), vec3(-b, -a, 0), //
138 vec3(-b, a, 0), vec3(-a, 0, -b), vec3(-a, 0, b), //
139 vec3(-b, -a, 0), vec3(-a, 0, b), vec3(-a, 0, -b), //
140 vec3(b, a, 0), vec3(a, 0, b), vec3(a, 0, -b), //
141 vec3(b, -a, 0), vec3(a, 0, -b), vec3(a, 0, b), //
142 vec3(0, b, a), vec3(-b, a, 0), vec3(-a, 0, b), //
143 vec3(0, b, a), vec3(a, 0, b), vec3(b, a, 0), //
144 vec3(0, b, -a), vec3(-a, 0, -b), vec3(-b, a, 0), //
145 vec3(0, b, -a), vec3(b, a, 0), vec3(a, 0, -b), //
146 vec3(0, -b, -a), vec3(-b, -a, 0), vec3(-a, 0, -b), //
147 vec3(0, -b, -a), vec3(a, 0, -b), vec3(b, -a, 0), //
148 vec3(0, -b, a), vec3(-a, 0, b), vec3(-b, -a, 0), //
149 vec3(0, -b, a), vec3(b, -a, 0), vec3(a, 0, b)
150 }; //
151 return vertices;
152}
107 153
108 // north pole154const VertexVector& tetrahedronVertices() {
109 *(vertex++) = 0.0f;155 static const float a = 1.0f / sqrt(2.0f);
110 *(vertex++) = 0.0f;156 static const auto A = vec3(0, 1, a);
111 *(vertex++) = 1.0f * radius;157 static const auto B = vec3(0, -1, a);
158 static const auto C = vec3(1, 0, -a);
159 static const auto D = vec3(-1, 0, -a);
160 static const VertexVector vertices{
161 A, B, C,
162 D, B, A,
163 C, D, A,
164 C, B, D,
165 };
166 return vertices;
167}
112 168
113 verticesBuffer->append(sizeof(GLfloat) * vertices * NUM_COORDS_PER_VERTEX, (gpu::Byte*) vertexData);169static const size_t TESSELTATION_MULTIPLIER = 4;
114 delete[] vertexData;170static const size_t ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT = 3;
171static const size_t VECTOR_TO_VECTOR_WITH_NORMAL_MULTIPLER = 2;
115 172
116 #ifdef WANT_DEBUG
117 qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING VERTICES BUFFER";
118 qCDebug(renderutils) << " radius:" << radius;
119 qCDebug(renderutils) << " slices:" << slices;
120 qCDebug(renderutils) << " stacks:" << stacks;
121 173
122 qCDebug(renderutils) << " _sphereVertices.size():" << _sphereVertices.size();174VertexVector tesselate(const VertexVector& startingTriangles, int count) {
123 #endif175 VertexVector triangles = startingTriangles;
176 if (0 != (triangles.size() % 3)) {
177 throw std::runtime_error("Bad number of vertices for tesselation");
124 }178 }
125 #ifdef WANT_DEBUG
126 else if (registered) {
127 qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED VERTICES BUFFER";
128 }
129 #endif
130 179
131 if ((registered && (!_registeredSphereIndices.contains(id) || _lastRegisteredSphereIndices[id] != slicesStacksKey))180 for (size_t i = 0; i < triangles.size(); ++i) {
132 || (!registered && !_sphereIndices.contains(slicesStacksKey))) {181 triangles[i] = glm::normalize(triangles[i]);
182 }
133 183
134 if (registered && _registeredSphereIndices.contains(id)) {184 VertexVector newTriangles;
135 _registeredSphereIndices[id].reset();185 while (count) {
136 #ifdef WANT_DEBUG186 newTriangles.clear();
137 qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED INDICES BUFFER";187 // Tesselation takes one triangle and makes it into 4 triangles
138 #endif188 // See https://en.wikipedia.org/wiki/Space-filling_tree#/media/File:Space_Filling_Tree_Tri_iter_1_2_3.png
189 newTriangles.reserve(triangles.size() * TESSELTATION_MULTIPLIER);
190 for (size_t i = 0; i < triangles.size(); i += VERTICES_PER_TRIANGLE) {
191 const vec3& a = triangles[i];
192 const vec3& b = triangles[i + 1];
193 const vec3& c = triangles[i + 2];
194 vec3 ab = glm::normalize(a + b);
195 vec3 bc = glm::normalize(b + c);
196 vec3 ca = glm::normalize(c + a);
197
198 newTriangles.push_back(a);
199 newTriangles.push_back(ab);
200 newTriangles.push_back(ca);
201
202 newTriangles.push_back(b);
203 newTriangles.push_back(bc);
204 newTriangles.push_back(ab);
205
206 newTriangles.push_back(c);
207 newTriangles.push_back(ca);
208 newTriangles.push_back(bc);
209
210 newTriangles.push_back(ab);
211 newTriangles.push_back(bc);
212 newTriangles.push_back(ca);
139 }213 }
214 triangles.swap(newTriangles);
215 --count;
216 }
217 return triangles;
218}
140 219
141 auto indicesBuffer = std::make_shared<gpu::Buffer>();220// FIXME solids need per-face vertices, but smooth shaded
142 if (registered) {221// components do not. Find a way to support using draw elements
143 _registeredSphereIndices[id] = indicesBuffer;222// or draw arrays as appropriate
144 _lastRegisteredSphereIndices[id] = slicesStacksKey;223// Maybe special case cone and cylinder since they combine flat
145 } else {224// and smooth shading
146 _sphereIndices[slicesStacksKey] = indicesBuffer;225void GeometryCache::buildShapes() {
226 auto vertexBuffer = std::make_shared<gpu::Buffer>();
227 auto indexBuffer = std::make_shared<gpu::Buffer>();
228 uint16_t startingIndex = 0;
229
230 // Cube
231 startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
232 {
233 ShapeData& shapeData = _shapes[Cube];
234 VertexVector vertices;
235 // front
236 vertices.push_back(vec3(1, 1, 1));
237 vertices.push_back(vec3(0, 0, 1));
238 vertices.push_back(vec3(-1, 1, 1));
239 vertices.push_back(vec3(0, 0, 1));
240 vertices.push_back(vec3(-1, -1, 1));
241 vertices.push_back(vec3(0, 0, 1));
242 vertices.push_back(vec3(1, -1, 1));
243 vertices.push_back(vec3(0, 0, 1));
244
245 // right
246 vertices.push_back(vec3(1, 1, 1));
247 vertices.push_back(vec3(1, 0, 0));
248 vertices.push_back(vec3(1, -1, 1));
249 vertices.push_back(vec3(1, 0, 0));
250 vertices.push_back(vec3(1, -1, -1));
251 vertices.push_back(vec3(1, 0, 0));
252 vertices.push_back(vec3(1, 1, -1));
253 vertices.push_back(vec3(1, 0, 0));
254
255 // top
256 vertices.push_back(vec3(1, 1, 1));
257 vertices.push_back(vec3(0, 1, 0));
258 vertices.push_back(vec3(1, 1, -1));
259 vertices.push_back(vec3(0, 1, 0));
260 vertices.push_back(vec3(-1, 1, -1));
261 vertices.push_back(vec3(0, 1, 0));
262 vertices.push_back(vec3(-1, 1, 1));
263 vertices.push_back(vec3(0, 1, 0));
264
265 // left
266 vertices.push_back(vec3(-1, 1, 1));
267 vertices.push_back(vec3(-1, 0, 0));
268 vertices.push_back(vec3(-1, 1, -1));
269 vertices.push_back(vec3(-1, 0, 0));
270 vertices.push_back(vec3(-1, -1, -1));
271 vertices.push_back(vec3(-1, 0, 0));
272 vertices.push_back(vec3(-1, -1, 1));
273 vertices.push_back(vec3(-1, 0, 0));
274
275 // bottom
276 vertices.push_back(vec3(-1, -1, -1));
277 vertices.push_back(vec3(0, -1, 0));
278 vertices.push_back(vec3(1, -1, -1));
279 vertices.push_back(vec3(0, -1, 0));
280 vertices.push_back(vec3(1, -1, 1));
281 vertices.push_back(vec3(0, -1, 0));
282 vertices.push_back(vec3(-1, -1, 1));
283 vertices.push_back(vec3(0, -1, 0));
284
285 // back
286 vertices.push_back(vec3(1, -1, -1));
287 vertices.push_back(vec3(0, 0, -1));
288 vertices.push_back(vec3(-1, -1, -1));
289 vertices.push_back(vec3(0, 0, -1));
290 vertices.push_back(vec3(-1, 1, -1));
291 vertices.push_back(vec3(0, 0, -1));
292 vertices.push_back(vec3(1, 1, -1));
293 vertices.push_back(vec3(0, 0, -1));
294
295 static const size_t VERTEX_FORMAT_SIZE = 2;
296 static const size_t VERTEX_OFFSET = 0;
297 static const size_t NORMAL_OFFSET = 1;
298
299 for (size_t i = 0; i < vertices.size(); ++i) {
300 auto vertexIndex = i;
301 // Make a unit cube by having the vertices (at index N)
302 // while leaving the normals (at index N + 1) alone
303 if (VERTEX_OFFSET == vertexIndex % VERTEX_FORMAT_SIZE) {
304 vertices[vertexIndex] *= 0.5f;
305 }
306 }
307 shapeData.setupVertices(_shapeVertices, vertices);
308
309 IndexVector indices{
310 0, 1, 2, 2, 3, 0, // front
311 4, 5, 6, 6, 7, 4, // right
312 8, 9, 10, 10, 11, 8, // top
313 12, 13, 14, 14, 15, 12, // left
314 16, 17, 18, 18, 19, 16, // bottom
315 20, 21, 22, 22, 23, 20 // back
316 };
317 for (auto& index : indices) {
318 index += startingIndex;
147 }319 }
148 320
149 GLushort* indexData = new GLushort[indices];321 IndexVector wireIndices{
150 GLushort* index = indexData;322 0, 1, 1, 2, 2, 3, 3, 0, // front
151 323 20, 21, 21, 22, 22, 23, 23, 20, // back
152 int indexCount = 0;324 0, 23, 1, 22, 2, 21, 3, 20 // sides
153 325 };
154 // South cap326 for (int i = 0; i < wireIndices.size(); ++i) {
155 GLushort bottom = 0;327 indices[i] += startingIndex;
156 GLushort top = 1;
157 for (int i = 0; i < slices; i++) {
158 *(index++) = bottom;
159 *(index++) = top + i;
160 *(index++) = top + (i + 1) % slices;
161
162 indexCount += 3;
163 }328 }
164 329
165 // (stacks - 2) ribbons330 shapeData.setupIndices(_shapeIndices, indices, wireIndices);
166 for (int i = 0; i < stacks - 2; i++) {331 }
167 bottom = i * slices + 1;
168 top = bottom + slices;
169 for (int j = 0; j < slices; j++) {
170 int next = (j + 1) % slices;
171
172 *(index++) = top + next;
173 *(index++) = bottom + j;
174 *(index++) = top + j;
175
176 indexCount += 3;
177
178 *(index++) = bottom + next;
179 *(index++) = bottom + j;
180 *(index++) = top + next;
181
182 indexCount += 3;
183 332
333 // Tetrahedron
334 startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
335 {
336 ShapeData& shapeData = _shapes[Tetrahedron];
337 size_t vertexCount = 4;
338 VertexVector vertices;
339 {
340 VertexVector originalVertices = tetrahedronVertices();
341 vertexCount = originalVertices.size();
342 vertices.reserve(originalVertices.size() * VECTOR_TO_VECTOR_WITH_NORMAL_MULTIPLER);
343 for (size_t i = 0; i < originalVertices.size(); i += VERTICES_PER_TRIANGLE) {
344 auto triangleStartIndex = i;
345 vec3 faceNormal;
346 for (size_t j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
347 auto triangleVertexIndex = j;
348 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
349 faceNormal += originalVertices[vertexIndex];
350 }
351 faceNormal = glm::normalize(faceNormal);
352 for (size_t j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
353 auto triangleVertexIndex = j;
354 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
355 vertices.push_back(glm::normalize(originalVertices[vertexIndex]));
356 vertices.push_back(faceNormal);
357 }
358 }
359 }
360 shapeData.setupVertices(_shapeVertices, vertices);
361
362 IndexVector indices;
363 for (size_t i = 0; i < vertexCount; i += VERTICES_PER_TRIANGLE) {
364 auto triangleStartIndex = i;
365 for (size_t j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
366 auto triangleVertexIndex = j;
367 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
368 indices.push_back(vertexIndex + startingIndex);
184 }369 }
185 }370 }
186
187 // north cap
188 bottom = (stacks - 2) * slices + 1;
189 top = bottom + slices;
190 for (int i = 0; i < slices; i++) {
191 *(index++) = bottom + (i + 1) % slices;
192 *(index++) = bottom + i;
193 *(index++) = top;
194
195 indexCount += 3;
196 371
372 IndexVector wireIndices{
373 0, 1, 1, 2, 2, 0,
374 0, 3, 1, 3, 2, 3,
375 };
376
377 for (int i = 0; i < wireIndices.size(); ++i) {
378 wireIndices[i] += startingIndex;
197 }379 }
198 indicesBuffer->append(sizeof(GLushort) * indices, (gpu::Byte*) indexData);
199 delete[] indexData;
200
201 #ifdef WANT_DEBUG
202 qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING INDICES BUFFER";
203 qCDebug(renderutils) << " radius:" << radius;
204 qCDebug(renderutils) << " slices:" << slices;
205 qCDebug(renderutils) << " stacks:" << stacks;
206 qCDebug(renderutils) << "indexCount:" << indexCount;
207 qCDebug(renderutils) << " indices:" << indices;
208 qCDebug(renderutils) << " _sphereIndices.size():" << _sphereIndices.size();
209 #endif
210 }
211 #ifdef WANT_DEBUG
212 else if (registered) {
213 qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED INDICES BUFFER";
214 }
215 #endif
216 380
217 if ((registered && (!_registeredSphereColors.contains(id) || _lastRegisteredSphereColors[id] != colorKey)) 381 shapeData.setupIndices(_shapeIndices, indices, wireIndices);
218 || (!registered && !_sphereColors.contains(colorKey))) {382 }
219 383
220 if (registered && _registeredSphereColors.contains(id)) {384 // Sphere
221 _registeredSphereColors[id].reset();385 // FIXME this uses way more vertices than required. Should find a way to calculate the indices
222 #ifdef WANT_DEBUG386 // using shared vertices for better vertex caching
223 qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED COLORS BUFFER";387 startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
224 #endif388 {
389 ShapeData& shapeData = _shapes[Sphere];
390 VertexVector vertices;
391 IndexVector indices;
392 {
393 VertexVector originalVertices = tesselate(icosahedronVertices(), ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT);
394 vertices.reserve(originalVertices.size() * VECTOR_TO_VECTOR_WITH_NORMAL_MULTIPLER);
395 for (size_t i = 0; i < originalVertices.size(); i += VERTICES_PER_TRIANGLE) {
396 auto triangleStartIndex = i;
397 for (int j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
398 auto triangleVertexIndex = j;
399 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
400 const auto& vertex = originalVertices[i + j];
401 // Spheres use the same values for vertices and normals
402 vertices.push_back(vertex);
403 vertices.push_back(vertex);
404 indices.push_back(vertexIndex + startingIndex);
405 }
406 }
225 }407 }
226 408
227 auto colorBuffer = std::make_shared<gpu::Buffer>();409 shapeData.setupVertices(_shapeVertices, vertices);
228 if (registered) {410 // FIXME don't use solid indices for wire drawing.
229 _registeredSphereColors[id] = colorBuffer;411 shapeData.setupIndices(_shapeIndices, indices, indices);
230 _lastRegisteredSphereColors[id] = colorKey;412 }
231 } else {413
232 _sphereColors[colorKey] = colorBuffer;414 // Icosahedron
415 startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
416 {
417 ShapeData& shapeData = _shapes[Icosahedron];
418
419 VertexVector vertices;
420 IndexVector indices;
421 {
422 const VertexVector& originalVertices = icosahedronVertices();
423 vertices.reserve(originalVertices.size() * VECTOR_TO_VECTOR_WITH_NORMAL_MULTIPLER);
424 for (size_t i = 0; i < originalVertices.size(); i += 3) {
425 auto triangleStartIndex = i;
426 vec3 faceNormal;
427 for (int j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
428 auto triangleVertexIndex = j;
429 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
430 faceNormal += originalVertices[vertexIndex];
431 }
432 faceNormal = glm::normalize(faceNormal);
433 for (int j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
434 auto triangleVertexIndex = j;
435 auto vertexIndex = triangleStartIndex + triangleVertexIndex;
436 vertices.push_back(glm::normalize(originalVertices[vertexIndex]));
437 vertices.push_back(faceNormal);
438 indices.push_back(vertexIndex + startingIndex);
439 }
440 }
233 }441 }
234 442
235 int compactColor = ((int(color.x * 255.0f) & 0xFF)) |443 shapeData.setupVertices(_shapeVertices, vertices);
236 ((int(color.y * 255.0f) & 0xFF) << 8) |444 // FIXME don't use solid indices for wire drawing.
237 ((int(color.z * 255.0f) & 0xFF) << 16) |445 shapeData.setupIndices(_shapeIndices, indices, indices);
238 ((int(color.w * 255.0f) & 0xFF) << 24);446 }
239 447
240 int* colorData = new int[vertices];448 // Line
241 int* colorDataAt = colorData;449 startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
450 {
451 ShapeData& shapeData = _shapes[Line];
452 shapeData.setupVertices(_shapeVertices, VertexVector{
453 vec3(-0.5, 0, 0), vec3(-0.5f, 0, 0),
454 vec3(0.5f, 0, 0), vec3(0.5f, 0, 0)
455 });
456 IndexVector wireIndices;
457 // Only two indices
458 wireIndices.push_back(0 + startingIndex);
459 wireIndices.push_back(1 + startingIndex);
460
461 shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices);
462 }
242 463
243 for(int v = 0; v < vertices; v++) {464 // Not implememented yet:
244 *(colorDataAt++) = compactColor;
245 }
246 465
247 colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData);466 //Triangle,
248 delete[] colorData;467 //Quad,
468 //Circle,
469 //Octahetron,
470 //Dodecahedron,
471 //Torus,
472 //Cone,
473 //Cylinder,
474}
249 475
250 #ifdef WANT_DEBUG476gpu::Stream::FormatPointer& getSolidStreamFormat() {
251 qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING COLORS BUFFER";477 if (!SOLID_STREAM_FORMAT) {
252 qCDebug(renderutils) << " vertices:" << vertices;478 SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
253 qCDebug(renderutils) << " color:" << color;479 SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
254 qCDebug(renderutils) << " slices:" << slices;480 SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
255 qCDebug(renderutils) << " stacks:" << stacks;
256 qCDebug(renderutils) << " _sphereColors.size():" << _sphereColors.size();
257 #endif
258 }
259 #ifdef WANT_DEBUG
260 else if (registered) {
261 qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED COLORS BUFFER";
262 }481 }
263 #endif482 return SOLID_STREAM_FORMAT;
483}
264 484
265 gpu::BufferPointer verticesBuffer = registered ? _registeredSphereVertices[id] : _sphereVertices[radiusKey];485gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
266 gpu::BufferPointer indicesBuffer = registered ? _registeredSphereIndices[id] : _sphereIndices[slicesStacksKey];486 if (!INSTANCED_SOLID_STREAM_FORMAT) {
267 gpu::BufferPointer colorBuffer = registered ? _registeredSphereColors[id] : _sphereColors[colorKey];487 INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
268 488 INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
269 const int VERTICES_SLOT = 0;489 INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
270 const int NORMALS_SLOT = 1;490 INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
271 const int COLOR_SLOT = 2;491 INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, TRANSFORM_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
272 static gpu::Stream::FormatPointer streamFormat;
273 static gpu::Element positionElement, normalElement, colorElement;
274 if (!streamFormat) {
275 streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
276 streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
277 streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ));
278 streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
279 positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
280 normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element;
281 colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
282 }492 }
493 return INSTANCED_SOLID_STREAM_FORMAT;
494}
283 495
284 gpu::BufferView verticesView(verticesBuffer, positionElement);496GeometryCache::GeometryCache() :
285 gpu::BufferView normalsView(verticesBuffer, normalElement);497 _nextID(0)
286 gpu::BufferView colorView(colorBuffer, colorElement);498{
287 499 buildShapes();
288 batch.setInputFormat(streamFormat);500}
289 batch.setInputBuffer(VERTICES_SLOT, verticesView);
290 batch.setInputBuffer(NORMALS_SLOT, normalsView);
291 batch.setInputBuffer(COLOR_SLOT, colorView);
292 batch.setIndexBuffer(gpu::UINT16, indicesBuffer, 0);
293 501
294 if (solid) {502GeometryCache::~GeometryCache() {
295 batch.drawIndexed(gpu::TRIANGLES, indices);503 #ifdef WANT_DEBUG
296 } else {504 qCDebug(renderutils) << "GeometryCache::~GeometryCache()... ";
297 batch.drawIndexed(gpu::LINES, indices);505 qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size();
298 }506 qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size();
507 qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;
508 #endif //def WANT_DEBUG
509}
510
511void setupBatchInstance(gpu::Batch& batch, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
512 gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
513 batch.setInputBuffer(gpu::Stream::COLOR, colorView);
514 gpu::BufferView instanceXfmView(transformBuffer, 0, transformBuffer->getSize(), TRANSFORM_ELEMENT);
515 batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
516}
517
518void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
519 batch.setInputFormat(getSolidStreamFormat());
520 _shapes[shape].draw(batch);
521}
522
523void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
524 batch.setInputFormat(getSolidStreamFormat());
525 _shapes[shape].drawWire(batch);
526}
527
528void GeometryCache::renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) {
529 batch.setInputFormat(getInstancedSolidStreamFormat());
530 setupBatchInstance(batch, transformBuffer, colorBuffer);
531 _shapes[shape].drawInstances(batch, count);
532}
533
534void GeometryCache::renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& transformBuffer, gpu::BufferPointer& colorBuffer) {
535 batch.setInputFormat(getInstancedSolidStreamFormat());
536 setupBatchInstance(batch, transformBuffer, colorBuffer);
537 _shapes[shape].drawWireInstances(batch, count);
538}
539
540void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
541 renderShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
542}
543
544void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
545 renderWireShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
546}
547
548void GeometryCache::renderCube(gpu::Batch& batch) {
549 renderShape(batch, Cube);
550}
551
552void GeometryCache::renderWireCube(gpu::Batch& batch) {
553 renderWireShape(batch, Cube);
554}
555
556void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
557 renderShapeInstances(batch, Sphere, count, transformBuffer, colorBuffer);
558}
559
560void GeometryCache::renderSphere(gpu::Batch& batch) {
561 renderShape(batch, Sphere);
562}
563
564void GeometryCache::renderWireSphere(gpu::Batch& batch) {
565 renderWireShape(batch, Sphere);
299}566}
300 567
568
301void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {569void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
302 IntPair key(xDivisions, yDivisions);570 IntPair key(xDivisions, yDivisions);
303 Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));571 Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions));
@@ -682,243 +950,6 @@ void GeometryCache::renderVertices(gpu::Batch& batch, gpu::Primitive primitiveTy · 378 unmodified lines
682 }950 }
683}951}
684 952
685static const int FLOATS_PER_VERTEX = 3;
686static const int VERTICES_PER_TRIANGLE = 3;
687
688static const int CUBE_NUMBER_OF_FACES = 6;
689static const int CUBE_VERTICES_PER_FACE = 4;
690static const int CUBE_TRIANGLES_PER_FACE = 2;
691static const int CUBE_VERTICES = CUBE_NUMBER_OF_FACES * CUBE_VERTICES_PER_FACE;
692static const int CUBE_VERTEX_POINTS = CUBE_VERTICES * FLOATS_PER_VERTEX;
693static const int CUBE_INDICES = CUBE_NUMBER_OF_FACES * CUBE_TRIANGLES_PER_FACE * VERTICES_PER_TRIANGLE;
694
695static const gpu::Element CUBE_POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
696static const gpu::Element CUBE_NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
697static const gpu::Element CUBE_COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
698static const gpu::Element INSTANCE_XFM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
699
700gpu::BufferPointer GeometryCache::getCubeVertices(float size) {
701 if (!_solidCubeVertices.contains(size)) {
702 auto verticesBuffer = std::make_shared<gpu::Buffer>();
703 _solidCubeVertices[size] = verticesBuffer;
704
705 GLfloat* vertexData = new GLfloat[CUBE_VERTEX_POINTS * 2]; // vertices and normals
706 GLfloat* vertex = vertexData;
707 float halfSize = size / 2.0f;
708
709 static GLfloat cannonicalVertices[CUBE_VERTEX_POINTS] =
710 { 1, 1, 1, -1, 1, 1, -1,-1, 1, 1,-1, 1, // v0,v1,v2,v3 (front)
711 1, 1, 1, 1,-1, 1, 1,-1,-1, 1, 1,-1, // v0,v3,v4,v5 (right)
712 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0,v5,v6,v1 (top)
713 -1, 1, 1, -1, 1,-1, -1,-1,-1, -1,-1, 1, // v1,v6,v7,v2 (left)
714 -1,-1,-1, 1,-1,-1, 1,-1, 1, -1,-1, 1, // v7,v4,v3,v2 (bottom)
715 1,-1,-1, -1,-1,-1, -1, 1,-1, 1, 1,-1 }; // v4,v7,v6,v5 (back)
716
717 // normal array
718 static GLfloat cannonicalNormals[CUBE_VERTEX_POINTS] =
719 { 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, // v0,v1,v2,v3 (front)
720 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, // v0,v3,v4,v5 (right)
721 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 0, // v0,v5,v6,v1 (top)
722 -1, 0, 0, -1, 0, 0, -1, 0, 0, -1, 0, 0, // v1,v6,v7,v2 (left)
723 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, // v7,v4,v3,v2 (bottom)
724 0, 0,-1, 0, 0,-1, 0, 0,-1, 0, 0,-1 }; // v4,v7,v6,v5 (back)
725
726
727 GLfloat* cannonicalVertex = &cannonicalVertices[0];
728 GLfloat* cannonicalNormal = &cannonicalNormals[0];
729
730 for (int i = 0; i < CUBE_VERTICES; i++) {
731 // vertices
732 *(vertex++) = halfSize * *cannonicalVertex++;
733 *(vertex++) = halfSize * *cannonicalVertex++;
734 *(vertex++) = halfSize * *cannonicalVertex++;
735
736 //normals
737 *(vertex++) = *cannonicalNormal++;
738 *(vertex++) = *cannonicalNormal++;
739 *(vertex++) = *cannonicalNormal++;
740 }
741 verticesBuffer->append(sizeof(GLfloat) * CUBE_VERTEX_POINTS * 2, (gpu::Byte*) vertexData);
742 }
743
744 return _solidCubeVertices[size];
745}
746
747gpu::BufferPointer GeometryCache::getSolidCubeIndices() {
748 if (!_solidCubeIndexBuffer) {
749 static GLubyte cannonicalIndices[CUBE_INDICES] = { 0, 1, 2, 2, 3, 0, // front
750 4, 5, 6, 6, 7, 4, // right
751 8, 9,10, 10,11, 8, // top
752 12,13,14, 14,15,12, // left
753 16,17,18, 18,19,16, // bottom
754 20,21,22, 22,23,20 }; // back
755
756 auto indexBuffer = std::make_shared<gpu::Buffer>();
757 _solidCubeIndexBuffer = indexBuffer;
758
759 _solidCubeIndexBuffer->append(sizeof(cannonicalIndices), (gpu::Byte*) cannonicalIndices);
760 }
761 return _solidCubeIndexBuffer;
762}
763
764
765void GeometryCache::setupCubeVertices(gpu::Batch& batch, gpu::BufferPointer& verticesBuffer) {
766 static const int VERTEX_STRIDE = sizeof(GLfloat) * FLOATS_PER_VERTEX * 2; // vertices and normals
767 static const int NORMALS_OFFSET = sizeof(GLfloat) * FLOATS_PER_VERTEX;
768
769 gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), VERTEX_STRIDE, CUBE_POSITION_ELEMENT);
770 gpu::BufferView normalsView(verticesBuffer, NORMALS_OFFSET, verticesBuffer->getSize(), VERTEX_STRIDE, CUBE_NORMAL_ELEMENT);
771 batch.setInputBuffer(gpu::Stream::POSITION, verticesView);
772 batch.setInputBuffer(gpu::Stream::NORMAL, normalsView);
773}
774
775void GeometryCache::renderSolidCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
776 static gpu::Stream::FormatPointer streamFormat;
777 if (!streamFormat) {
778 streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
779 streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, CUBE_POSITION_ELEMENT, 0);
780 streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, CUBE_NORMAL_ELEMENT);
781 streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, CUBE_COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
782 streamFormat->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, INSTANCE_XFM_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
783 }
784 batch.setInputFormat(streamFormat);
785
786 gpu::BufferView colorView(colorBuffer, CUBE_COLOR_ELEMENT);
787 batch.setInputBuffer(gpu::Stream::COLOR, colorView);
788
789 gpu::BufferView instanceXfmView(transformBuffer, 0, transformBuffer->getSize(), INSTANCE_XFM_ELEMENT);
790 batch.setInputBuffer(gpu::Stream::INSTANCE_XFM, instanceXfmView);
791
792 gpu::BufferPointer verticesBuffer = getCubeVertices(1.0);
793 setupCubeVertices(batch, verticesBuffer);
794 batch.setIndexBuffer(gpu::UINT8, getSolidCubeIndices(), 0);
795 batch.drawIndexedInstanced(count, gpu::TRIANGLES, CUBE_INDICES);
796}
797
798
799void GeometryCache::renderSolidCube(gpu::Batch& batch, float size, const glm::vec4& color) {
800 Vec2Pair colorKey(glm::vec2(color.x, color.y), glm::vec2(color.z, color.y));
801 if (!_solidCubeColors.contains(colorKey)) {
802 auto colorBuffer = std::make_shared<gpu::Buffer>();
803 _solidCubeColors[colorKey] = colorBuffer;
804
805 int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
806 ((int(color.y * 255.0f) & 0xFF) << 8) |
807 ((int(color.z * 255.0f) & 0xFF) << 16) |
808 ((int(color.w * 255.0f) & 0xFF) << 24);
809 int colors[CUBE_VERTICES] = {
810 compactColor, compactColor, compactColor, compactColor,
811 compactColor, compactColor, compactColor, compactColor,
812 compactColor, compactColor, compactColor, compactColor,
813 compactColor, compactColor, compactColor, compactColor,
814 compactColor, compactColor, compactColor, compactColor,
815 compactColor, compactColor, compactColor, compactColor
816 };
817 colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
818 }
819 gpu::BufferPointer colorBuffer = _solidCubeColors[colorKey];
820
821 static gpu::Stream::FormatPointer streamFormat;
822 if (!streamFormat) {
823 streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
824 streamFormat->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, CUBE_POSITION_ELEMENT, 0);
825 streamFormat->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, CUBE_NORMAL_ELEMENT);
826 streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, CUBE_COLOR_ELEMENT);
827 }
828 batch.setInputFormat(streamFormat);
829
830 gpu::BufferView colorView(colorBuffer, CUBE_COLOR_ELEMENT);
831 batch.setInputBuffer(gpu::Stream::COLOR, colorView);
832
833 gpu::BufferPointer verticesBuffer = getCubeVertices(size);
834 setupCubeVertices(batch, verticesBuffer);
835
836 batch.setIndexBuffer(gpu::UINT8, getSolidCubeIndices(), 0);
837 batch.drawIndexed(gpu::TRIANGLES, CUBE_INDICES);
838}
839
840
841void GeometryCache::renderWireCube(gpu::Batch& batch, float size, const glm::vec4& color) {
842 Vec2Pair colorKey(glm::vec2(color.x, color.y),glm::vec2(color.z, color.y));
843 static const int WIRE_CUBE_VERTICES_PER_EDGE = 2;
844 static const int WIRE_CUBE_TOP_EDGES = 4;
845 static const int WIRE_CUBE_BOTTOM_EDGES = 4;
846 static const int WIRE_CUBE_SIDE_EDGES = 4;
847 static const int WIRE_CUBE_VERTICES = 8;
848 static const int WIRE_CUBE_INDICES = (WIRE_CUBE_TOP_EDGES + WIRE_CUBE_BOTTOM_EDGES + WIRE_CUBE_SIDE_EDGES) * WIRE_CUBE_VERTICES_PER_EDGE;
849
850 if (!_cubeVerticies.contains(size)) {
851 auto verticesBuffer = std::make_shared<gpu::Buffer>();
852 _cubeVerticies[size] = verticesBuffer;
853
854 static const int WIRE_CUBE_VERTEX_POINTS = WIRE_CUBE_VERTICES * FLOATS_PER_VERTEX;
855 GLfloat* vertexData = new GLfloat[WIRE_CUBE_VERTEX_POINTS]; // only vertices, no normals because we're a wire cube
856 GLfloat* vertex = vertexData;
857 float halfSize = size / 2.0f;
858
859 static GLfloat cannonicalVertices[] =
860 { 1, 1, 1, 1, 1,-1, -1, 1,-1, -1, 1, 1, // v0, v1, v2, v3 (top)
861 1,-1, 1, 1,-1,-1, -1,-1,-1, -1,-1, 1 // v4, v5, v6, v7 (bottom)
862 };
863
864 for (int i = 0; i < WIRE_CUBE_VERTEX_POINTS; i++) {
865 vertex[i] = cannonicalVertices[i] * halfSize;
866 }
867
868 verticesBuffer->append(sizeof(GLfloat) * WIRE_CUBE_VERTEX_POINTS, (gpu::Byte*) vertexData); // I'm skeptical that this is right
869 }
870
871 if (!_wireCubeIndexBuffer) {
872 static GLubyte cannonicalIndices[WIRE_CUBE_INDICES] = {
873 0, 1, 1, 2, 2, 3, 3, 0, // (top)
874 4, 5, 5, 6, 6, 7, 7, 4, // (bottom)
875 0, 4, 1, 5, 2, 6, 3, 7, // (side edges)
876 };
877
878 auto indexBuffer = std::make_shared<gpu::Buffer>();
879 _wireCubeIndexBuffer = indexBuffer;
880
881 _wireCubeIndexBuffer->append(sizeof(cannonicalIndices), (gpu::Byte*) cannonicalIndices);
882 }
883
884 if (!_cubeColors.contains(colorKey)) {
885 auto colorBuffer = std::make_shared<gpu::Buffer>();
886 _cubeColors[colorKey] = colorBuffer;
887
888 const int NUM_COLOR_SCALARS_PER_CUBE = 8;
889 int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
890 ((int(color.y * 255.0f) & 0xFF) << 8) |
891 ((int(color.z * 255.0f) & 0xFF) << 16) |
892 ((int(color.w * 255.0f) & 0xFF) << 24);
893 int colors[NUM_COLOR_SCALARS_PER_CUBE] = { compactColor, compactColor, compactColor, compactColor,
894 compactColor, compactColor, compactColor, compactColor };
895
896 colorBuffer->append(sizeof(colors), (gpu::Byte*) colors);
897 }
898 gpu::BufferPointer verticesBuffer = _cubeVerticies[size];
899 gpu::BufferPointer colorBuffer = _cubeColors[colorKey];
900
901 const int VERTICES_SLOT = 0;
902 const int COLOR_SLOT = 1;
903 static gpu::Stream::FormatPointer streamFormat;
904 static gpu::Element positionElement, colorElement;
905 if (!streamFormat) {
906 streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
907 streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0);
908 streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::NUINT8, gpu::RGBA));
909 positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element;
910 colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element;
911 }
912
913 gpu::BufferView verticesView(verticesBuffer, positionElement);
914 gpu::BufferView colorView(colorBuffer, colorElement);
915
916 batch.setInputFormat(streamFormat);
917 batch.setInputBuffer(VERTICES_SLOT, verticesView);
918 batch.setInputBuffer(COLOR_SLOT, colorView);
919 batch.setIndexBuffer(gpu::UINT8, _wireCubeIndexBuffer, 0);
920 batch.drawIndexed(gpu::LINES, WIRE_CUBE_INDICES);
921}
922 953
923void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {954void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
924 bool registered = (id != UNKNOWN_ID);955 bool registered = (id != UNKNOWN_ID);
@@ -1092,11 +1123,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co · 167 unmodified lines
1092 batch.draw(gpu::TRIANGLE_STRIP, 4, 0);1123 batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
1093}1124}
1094 1125
1095void GeometryCache::renderUnitCube(gpu::Batch& batch) {
1096 static const glm::vec4 color(1);
1097 renderSolidCube(batch, 1, color);
1098}
1099
1100void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {1126void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {
1101 static const glm::vec2 topLeft(-1, 1);1127 static const glm::vec2 topLeft(-1, 1);
1102 static const glm::vec2 bottomRight(1, -1);1128 static const glm::vec2 bottomRight(1, -1);