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
3535
3636 const int GeometryCache::UNKNOWN_ID = -1;
3737
38−GeometryCache::GeometryCache() :
39− _nextID(0)
40−{
41−}
4238
43−GeometryCache::~GeometryCache() {
44− #ifdef WANT_DEBUG
45− qCDebug(renderutils) << "GeometryCache::~GeometryCache()... ";
46− qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size();
47− qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size();
48− qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;
49− #endif //def WANT_DEBUG
39+static const uint FLOATS_PER_VERTEX = 3;
40+static const uint VERTICES_PER_TRIANGLE = 3;
41+static const uint TRIANGLES_PER_QUAD = 2;
42+static const uint CUBE_FACES = 6;
43+static const uint CUBE_VERTICES_PER_FACE = 4;
44+static const uint CUBE_VERTICES = CUBE_FACES * CUBE_VERTICES_PER_FACE;
45+static const uint CUBE_VERTEX_POINTS = CUBE_VERTICES * FLOATS_PER_VERTEX;
46+static const uint CUBE_INDICES = CUBE_FACES * TRIANGLES_PER_QUAD * VERTICES_PER_TRIANGLE;
47+static const uint SPHERE_LATITUDES = 24;
48+static const uint SPHERE_MERIDIANS = SPHERE_LATITUDES * 2;
49+static const uint SPHERE_INDICES = SPHERE_MERIDIANS * (SPHERE_LATITUDES - 1) * TRIANGLES_PER_QUAD * VERTICES_PER_TRIANGLE;
50+
51+static const gpu::Element POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
52+static const gpu::Element NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
53+static const gpu::Element COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
54+static const gpu::Element TRANSFORM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
55+
56+static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;
57+static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;
58+
59+static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normals
60+static const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);
61+
62+
63+void 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);
5070 }
5171
52−const int NUM_VERTICES_PER_TRIANGLE = 3;
53−const int NUM_TRIANGLES_PER_QUAD = 2;
54−const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;
55−const int NUM_COORDS_PER_VERTEX = 3;
56−
57−void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) {
58− bool registered = (id != UNKNOWN_ID);
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;
72+void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const IndexVector& indices, const IndexVector& wireIndices) {
73+ _indices = indexBuffer;
74+ if (!indices.empty()) {
75+ _indexOffset = indexBuffer->getSize();
76+ _indexCount = indices.size();
77+ indexBuffer->append(indices);
78+ }
6679
67− if ((registered && (!_registeredSphereVertices.contains(id) || _lastRegisteredSphereVertices[id] != radiusKey))
68− || (!registered && !_sphereVertices.contains(radiusKey))) {
80+ if (!wireIndices.empty()) {
81+ _wireIndexOffset = indexBuffer->getSize();
82+ _wireIndexCount = wireIndices.size();
83+ indexBuffer->append(wireIndices);
84+ }
85+}
6986
70− if (registered && _registeredSphereVertices.contains(id)) {
71− _registeredSphereVertices[id].reset();
72− #ifdef WANT_DEBUG
73− qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED VERTICES BUFFER";
74− #endif
75− }
87+void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {
88+ batch.setInputBuffer(gpu::Stream::POSITION, _positionView);
89+ batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);
90+}
7691
77− auto verticesBuffer = std::make_shared<gpu::Buffer>();
78− if (registered) {
79− _registeredSphereVertices[id] = verticesBuffer;
80− _lastRegisteredSphereVertices[id] = radiusKey;
81− } else {
82− _sphereVertices[radiusKey] = verticesBuffer;
83− }
92+void GeometryCache::ShapeData::draw(gpu::Batch& batch) const {
93+ if (_indexCount) {
94+ setupBatch(batch);
95+ batch.setIndexBuffer(gpu::UINT16, _indices, _indexOffset);
96+ batch.drawIndexed(gpu::TRIANGLES, _indexCount);
97+ }
98+}
8499
85− GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];
86− GLfloat* vertex = vertexData;
100+void GeometryCache::ShapeData::drawWire(gpu::Batch& batch) const {
101+ if (_wireIndexCount) {
102+ setupBatch(batch);
103+ batch.setIndexBuffer(gpu::UINT16, _indices, _wireIndexOffset);
104+ batch.drawIndexed(gpu::LINES, _wireIndexCount);
105+ }
106+}
87107
88− // south pole
89− *(vertex++) = 0.0f;
90− *(vertex++) = 0.0f;
91− *(vertex++) = -1.0f * radius;
108+void GeometryCache::ShapeData::drawInstances(gpu::Batch& batch, size_t count) const {
109+ if (_indexCount) {
110+ setupBatch(batch);
111+ batch.setIndexBuffer(gpu::UINT16, _indices, _indexOffset);
112+ batch.drawIndexedInstanced(count, gpu::TRIANGLES, _indexCount);
113+ }
114+}
92115
93− //add stacks vertices climbing up Y axis
94− for (int i = 1; i < stacks; i++) {
95− float phi = PI * (float)i / (float)(stacks) - PI_OVER_TWO;
96− float z = sinf(phi) * radius;
97− float stackRadius = cosf(phi) * radius;
98−
99− for (int j = 0; j < slices; j++) {
100− float theta = TWO_PI * (float)j / (float)slices;
116+void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count) const {
117+ if (_wireIndexCount) {
118+ setupBatch(batch);
119+ batch.setIndexBuffer(gpu::UINT16, _indices, _wireIndexOffset);
120+ batch.drawIndexedInstanced(count, gpu::LINES, _wireIndexCount);
121+ }
122+}
101123
102− *(vertex++) = sinf(theta) * stackRadius;
103− *(vertex++) = cosf(theta) * stackRadius;
104− *(vertex++) = z;
105− }
106− }
124+const VertexVector& icosahedronVertices() {
125+ static const float phi = (1.0 + sqrt(5.0)) / 2.0;
126+ static const float a = 0.5;
127+ static const float b = 1.0 / (2.0 * phi);
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+}
107153
108− // north pole
109− *(vertex++) = 0.0f;
110− *(vertex++) = 0.0f;
111− *(vertex++) = 1.0f * radius;
154+const VertexVector& tetrahedronVertices() {
155+ static const float a = 1.0f / sqrt(2.0f);
156+ static const auto A = vec3(0, 1, a);
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+}
112168
113− verticesBuffer->append(sizeof(GLfloat) * vertices * NUM_COORDS_PER_VERTEX, (gpu::Byte*) vertexData);
114− delete[] vertexData;
169+static const size_t TESSELTATION_MULTIPLIER = 4;
170+static const size_t ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT = 3;
171+static const size_t VECTOR_TO_VECTOR_WITH_NORMAL_MULTIPLER = 2;
115172
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;
121173
122− qCDebug(renderutils) << " _sphereVertices.size():" << _sphereVertices.size();
123− #endif
174+VertexVector tesselate(const VertexVector& startingTriangles, int count) {
175+ VertexVector triangles = startingTriangles;
176+ if (0 != (triangles.size() % 3)) {
177+ throw std::runtime_error("Bad number of vertices for tesselation");
124178 }
125− #ifdef WANT_DEBUG
126− else if (registered) {
127− qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED VERTICES BUFFER";
128− }
129− #endif
130179
131− if ((registered && (!_registeredSphereIndices.contains(id) || _lastRegisteredSphereIndices[id] != slicesStacksKey))
132− || (!registered && !_sphereIndices.contains(slicesStacksKey))) {
180+ for (size_t i = 0; i < triangles.size(); ++i) {
181+ triangles[i] = glm::normalize(triangles[i]);
182+ }
133183
134− if (registered && _registeredSphereIndices.contains(id)) {
135− _registeredSphereIndices[id].reset();
136− #ifdef WANT_DEBUG
137− qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED INDICES BUFFER";
138− #endif
184+ VertexVector newTriangles;
185+ while (count) {
186+ newTriangles.clear();
187+ // Tesselation takes one triangle and makes it into 4 triangles
188+ // 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);
139213 }
214+ triangles.swap(newTriangles);
215+ --count;
216+ }
217+ return triangles;
218+}
140219
141− auto indicesBuffer = std::make_shared<gpu::Buffer>();
142− if (registered) {
143− _registeredSphereIndices[id] = indicesBuffer;
144− _lastRegisteredSphereIndices[id] = slicesStacksKey;
145− } else {
146− _sphereIndices[slicesStacksKey] = indicesBuffer;
220+// FIXME solids need per-face vertices, but smooth shaded
221+// components do not. Find a way to support using draw elements
222+// or draw arrays as appropriate
223+// Maybe special case cone and cylinder since they combine flat
224+// and smooth shading
225+void 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;
147319 }
148320
149− GLushort* indexData = new GLushort[indices];
150− GLushort* index = indexData;
151−
152− int indexCount = 0;
153−
154− // South cap
155− GLushort bottom = 0;
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;
321+ IndexVector wireIndices{
322+ 0, 1, 1, 2, 2, 3, 3, 0, // front
323+ 20, 21, 21, 22, 22, 23, 23, 20, // back
324+ 0, 23, 1, 22, 2, 21, 3, 20 // sides
325+ };
326+ for (int i = 0; i < wireIndices.size(); ++i) {
327+ indices[i] += startingIndex;
163328 }
164329
165− // (stacks - 2) ribbons
166− for (int i = 0; i < stacks - 2; i++) {
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;
330+ shapeData.setupIndices(_shapeIndices, indices, wireIndices);
331+ }
183332
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);
184369 }
185370 }
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;
196371
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;
197379 }
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
216380
217− if ((registered && (!_registeredSphereColors.contains(id) || _lastRegisteredSphereColors[id] != colorKey))
218− || (!registered && !_sphereColors.contains(colorKey))) {
381+ shapeData.setupIndices(_shapeIndices, indices, wireIndices);
382+ }
219383
220− if (registered && _registeredSphereColors.contains(id)) {
221− _registeredSphereColors[id].reset();
222− #ifdef WANT_DEBUG
223− qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED COLORS BUFFER";
224− #endif
384+ // Sphere
385+ // FIXME this uses way more vertices than required. Should find a way to calculate the indices
386+ // using shared vertices for better vertex caching
387+ startingIndex = _shapeVertices->getSize() / SHAPE_VERTEX_STRIDE;
388+ {
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+ }
225407 }
226408
227− auto colorBuffer = std::make_shared<gpu::Buffer>();
228− if (registered) {
229− _registeredSphereColors[id] = colorBuffer;
230− _lastRegisteredSphereColors[id] = colorKey;
231− } else {
232− _sphereColors[colorKey] = colorBuffer;
409+ shapeData.setupVertices(_shapeVertices, vertices);
410+ // FIXME don't use solid indices for wire drawing.
411+ shapeData.setupIndices(_shapeIndices, indices, indices);
412+ }
413+
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+ }
233441 }
234442
235− int compactColor = ((int(color.x * 255.0f) & 0xFF)) |
236− ((int(color.y * 255.0f) & 0xFF) << 8) |
237− ((int(color.z * 255.0f) & 0xFF) << 16) |
238− ((int(color.w * 255.0f) & 0xFF) << 24);
443+ shapeData.setupVertices(_shapeVertices, vertices);
444+ // FIXME don't use solid indices for wire drawing.
445+ shapeData.setupIndices(_shapeIndices, indices, indices);
446+ }
239447
240− int* colorData = new int[vertices];
241− int* colorDataAt = colorData;
448+ // Line
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+ }
242463
243− for(int v = 0; v < vertices; v++) {
244− *(colorDataAt++) = compactColor;
245− }
464+ // Not implememented yet:
246465
247− colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData);
248− delete[] colorData;
466+ //Triangle,
467+ //Quad,
468+ //Circle,
469+ //Octahetron,
470+ //Dodecahedron,
471+ //Torus,
472+ //Cone,
473+ //Cylinder,
474+}
249475
250− #ifdef WANT_DEBUG
251− qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING COLORS BUFFER";
252− qCDebug(renderutils) << " vertices:" << vertices;
253− qCDebug(renderutils) << " color:" << color;
254− qCDebug(renderutils) << " slices:" << slices;
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";
476+gpu::Stream::FormatPointer& getSolidStreamFormat() {
477+ if (!SOLID_STREAM_FORMAT) {
478+ SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
479+ SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
480+ SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
262481 }
263− #endif
482+ return SOLID_STREAM_FORMAT;
483+}
264484
265− gpu::BufferPointer verticesBuffer = registered ? _registeredSphereVertices[id] : _sphereVertices[radiusKey];
266− gpu::BufferPointer indicesBuffer = registered ? _registeredSphereIndices[id] : _sphereIndices[slicesStacksKey];
267− gpu::BufferPointer colorBuffer = registered ? _registeredSphereColors[id] : _sphereColors[colorKey];
268−
269− const int VERTICES_SLOT = 0;
270− const int NORMALS_SLOT = 1;
271− const int COLOR_SLOT = 2;
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;
485+gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {
486+ if (!INSTANCED_SOLID_STREAM_FORMAT) {
487+ INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone
488+ INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);
489+ INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);
490+ INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
491+ INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::INSTANCE_XFM, gpu::Stream::INSTANCE_XFM, TRANSFORM_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
282492 }
493+ return INSTANCED_SOLID_STREAM_FORMAT;
494+}
283495
284− gpu::BufferView verticesView(verticesBuffer, positionElement);
285− gpu::BufferView normalsView(verticesBuffer, normalElement);
286− gpu::BufferView colorView(colorBuffer, colorElement);
287−
288− batch.setInputFormat(streamFormat);
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);
496+GeometryCache::GeometryCache() :
497+ _nextID(0)
498+{
499+ buildShapes();
500+}
293501
294− if (solid) {
295− batch.drawIndexed(gpu::TRIANGLES, indices);
296− } else {
297− batch.drawIndexed(gpu::LINES, indices);
298− }
502+GeometryCache::~GeometryCache() {
503+ #ifdef WANT_DEBUG
504+ qCDebug(renderutils) << "GeometryCache::~GeometryCache()... ";
505+ qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size();
506+ qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size();
507+ qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;
508+ #endif //def WANT_DEBUG
509+}
510+
511+void 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+
518+void GeometryCache::renderShape(gpu::Batch& batch, Shape shape) {
519+ batch.setInputFormat(getSolidStreamFormat());
520+ _shapes[shape].draw(batch);
521+}
522+
523+void GeometryCache::renderWireShape(gpu::Batch& batch, Shape shape) {
524+ batch.setInputFormat(getSolidStreamFormat());
525+ _shapes[shape].drawWire(batch);
526+}
527+
528+void 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+
534+void 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+
540+void GeometryCache::renderCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
541+ renderShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
542+}
543+
544+void GeometryCache::renderWireCubeInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
545+ renderWireShapeInstances(batch, Cube, count, transformBuffer, colorBuffer);
546+}
547+
548+void GeometryCache::renderCube(gpu::Batch& batch) {
549+ renderShape(batch, Cube);
550+}
551+
552+void GeometryCache::renderWireCube(gpu::Batch& batch) {
553+ renderWireShape(batch, Cube);
554+}
555+
556+void GeometryCache::renderSphereInstances(gpu::Batch& batch, size_t count, gpu::BufferPointer transformBuffer, gpu::BufferPointer colorBuffer) {
557+ renderShapeInstances(batch, Sphere, count, transformBuffer, colorBuffer);
558+}
559+
560+void GeometryCache::renderSphere(gpu::Batch& batch) {
561+ renderShape(batch, Sphere);
562+}
563+
564+void GeometryCache::renderWireSphere(gpu::Batch& batch) {
565+ renderWireShape(batch, Sphere);
299566 }
300567
568+
301569 void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) {
302570 IntPair key(xDivisions, yDivisions);
303571 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
682950 }
683951 }
684952
685−static const int FLOATS_PER_VERTEX = 3;
686−static const int VERTICES_PER_TRIANGLE = 3;
687−
688−static const int CUBE_NUMBER_OF_FACES = 6;
689−static const int CUBE_VERTICES_PER_FACE = 4;
690−static const int CUBE_TRIANGLES_PER_FACE = 2;
691−static const int CUBE_VERTICES = CUBE_NUMBER_OF_FACES * CUBE_VERTICES_PER_FACE;
692−static const int CUBE_VERTEX_POINTS = CUBE_VERTICES * FLOATS_PER_VERTEX;
693−static const int CUBE_INDICES = CUBE_NUMBER_OF_FACES * CUBE_TRIANGLES_PER_FACE * VERTICES_PER_TRIANGLE;
694−
695−static const gpu::Element CUBE_POSITION_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
696−static const gpu::Element CUBE_NORMAL_ELEMENT{ gpu::VEC3, gpu::FLOAT, gpu::XYZ };
697−static const gpu::Element CUBE_COLOR_ELEMENT{ gpu::VEC4, gpu::NUINT8, gpu::RGBA };
698−static const gpu::Element INSTANCE_XFM_ELEMENT{ gpu::MAT4, gpu::FLOAT, gpu::XYZW };
699−
700−gpu::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−
747−gpu::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−
765−void 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−
775−void 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−
799−void 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−
841−void 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−}
922953
923954 void GeometryCache::renderBevelCornersRect(gpu::Batch& batch, int x, int y, int width, int height, int bevelDistance, const glm::vec4& color, int id) {
924955 bool registered = (id != UNKNOWN_ID);
@@ -1092,11 +1123,6 @@ void GeometryCache::renderQuad(gpu::Batch& batch, const glm::vec2& minCorner, co · 167 unmodified lines
10921123 batch.draw(gpu::TRIANGLE_STRIP, 4, 0);
10931124 }
10941125
1095−void GeometryCache::renderUnitCube(gpu::Batch& batch) {
1096− static const glm::vec4 color(1);
1097− renderSolidCube(batch, 1, color);
1098−}
1099−
11001126 void GeometryCache::renderUnitQuad(gpu::Batch& batch, const glm::vec4& color, int id) {
11011127 static const glm::vec2 topLeft(-1, 1);
11021128 static const glm::vec2 bottomRight(1, -1);