//// GeometryCache.cpp// interface/src/renderer//// Created by Andrzej Kapolka on 6/21/13.// Copyright 2013 High Fidelity, Inc.//// Distributed under the Apache License, Version 2.0.// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html// // include this before QOpenGLBuffer, which includes an earlier version of OpenGL#include <cmath> #include <QNetworkReply>#include <QRunnable>#include <QThreadPool> #include <gpu/Batch.h>#include <gpu/GLBackend.h> #include <FSTReader.h>#include <NumericalConstants.h> #include "TextureCache.h"#include "RenderUtilsLogging.h"#include "GeometryCache.h" #include "standardTransformPNTC_vert.h"#include "standardDrawTexture_frag.h" #include "gpu/StandardShaderLib.h" //#define WANT_DEBUG const int GeometryCache::UNKNOWN_ID = -1; GeometryCache::GeometryCache() : _nextID(0){ const qint64 GEOMETRY_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(GEOMETRY_DEFAULT_UNUSED_MAX_SIZE);} GeometryCache::~GeometryCache() { #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population; #endif //def WANT_DEBUG} const int NUM_VERTICES_PER_TRIANGLE = 3;const int NUM_TRIANGLES_PER_QUAD = 2;const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;const int NUM_COORDS_PER_VERTEX = 3; void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) { bool registered = (id != UNKNOWN_ID); Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0)); IntPair slicesStacksKey(slices, stacks); Vec3Pair colorKey(glm::vec3(color.x, color.y, slices), glm::vec3(color.z, color.w, stacks)); int vertices = slices * (stacks - 1) + 2; int indices = slices * (stacks - 1) * NUM_VERTICES_PER_TRIANGULATED_QUAD; if ((registered && (!_registeredSphereVertices.contains(id) || _lastRegisteredSphereVertices[id] != radiusKey)) || (!registered && !_sphereVertices.contains(radiusKey))) { if (registered && _registeredSphereVertices.contains(id)) { _registeredSphereVertices[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED VERTICES BUFFER"; #endif } auto verticesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereVertices[id] = verticesBuffer; _lastRegisteredSphereVertices[id] = radiusKey; } else { _sphereVertices[radiusKey] = verticesBuffer; } GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX]; GLfloat* vertex = vertexData; // south pole *(vertex++) = 0.0f; *(vertex++) = 0.0f; *(vertex++) = -1.0f * radius; //add stacks vertices climbing up Y axis for (int i = 1; i < stacks; i++) { float phi = PI * (float)i / (float)(stacks) - PI_OVER_TWO; float z = sinf(phi) * radius; float stackRadius = cosf(phi) * radius; for (int j = 0; j < slices; j++) { float theta = TWO_PI * (float)j / (float)slices; *(vertex++) = sinf(theta) * stackRadius; *(vertex++) = cosf(theta) * stackRadius; *(vertex++) = z; } } // north pole *(vertex++) = 0.0f; *(vertex++) = 0.0f; *(vertex++) = 1.0f * radius; verticesBuffer->append(sizeof(GLfloat) * vertices * NUM_COORDS_PER_VERTEX, (gpu::Byte*) vertexData); delete[] vertexData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING VERTICES BUFFER"; qCDebug(renderutils) << " radius:" << radius; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << " _sphereVertices.size():" << _sphereVertices.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED VERTICES BUFFER"; } #endif if ((registered && (!_registeredSphereIndices.contains(id) || _lastRegisteredSphereIndices[id] != slicesStacksKey)) || (!registered && !_sphereIndices.contains(slicesStacksKey))) { if (registered && _registeredSphereIndices.contains(id)) { _registeredSphereIndices[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED INDICES BUFFER"; #endif } auto indicesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereIndices[id] = indicesBuffer; _lastRegisteredSphereIndices[id] = slicesStacksKey; } else { _sphereIndices[slicesStacksKey] = indicesBuffer; } GLushort* indexData = new GLushort[indices]; GLushort* index = indexData; int indexCount = 0; // South cap GLushort bottom = 0; GLushort top = 1; for (int i = 0; i < slices; i++) { *(index++) = bottom; *(index++) = top + i; *(index++) = top + (i + 1) % slices; indexCount += 3; } // (stacks - 2) ribbons for (int i = 0; i < stacks - 2; i++) { bottom = i * slices + 1; top = bottom + slices; for (int j = 0; j < slices; j++) { int next = (j + 1) % slices; *(index++) = top + next; *(index++) = bottom + j; *(index++) = top + j; indexCount += 3; *(index++) = bottom + next; *(index++) = bottom + j; *(index++) = top + next; indexCount += 3; } } // north cap bottom = (stacks - 2) * slices + 1; top = bottom + slices; for (int i = 0; i < slices; i++) { *(index++) = bottom + (i + 1) % slices; *(index++) = bottom + i; *(index++) = top; indexCount += 3; } indicesBuffer->append(sizeof(GLushort) * indices, (gpu::Byte*) indexData); delete[] indexData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING INDICES BUFFER"; qCDebug(renderutils) << " radius:" << radius; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << "indexCount:" << indexCount; qCDebug(renderutils) << " indices:" << indices; qCDebug(renderutils) << " _sphereIndices.size():" << _sphereIndices.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED INDICES BUFFER"; } #endif if ((registered && (!_registeredSphereColors.contains(id) || _lastRegisteredSphereColors[id] != colorKey)) || (!registered && !_sphereColors.contains(colorKey))) { if (registered && _registeredSphereColors.contains(id)) { _registeredSphereColors[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED COLORS BUFFER"; #endif } auto colorBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereColors[id] = colorBuffer; _lastRegisteredSphereColors[id] = colorKey; } else { _sphereColors[colorKey] = colorBuffer; } int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING COLORS BUFFER"; qCDebug(renderutils) << " vertices:" << vertices; qCDebug(renderutils) << " color:" << color; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << " _sphereColors.size():" << _sphereColors.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED COLORS BUFFER"; } #endif gpu::BufferPointer verticesBuffer = registered ? _registeredSphereVertices[id] : _sphereVertices[radiusKey]; gpu::BufferPointer indicesBuffer = registered ? _registeredSphereIndices[id] : _sphereIndices[slicesStacksKey]; gpu::BufferPointer colorBuffer = registered ? _registeredSphereColors[id] : _sphereColors[colorKey]; const int VERTICES_SLOT = 0; const int NORMALS_SLOT = 1; const int COLOR_SLOT = 2; static gpu::Stream::FormatPointer streamFormat; static gpu::Element positionElement, normalElement, colorElement; if (!streamFormat) { streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element; colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; } gpu::BufferView verticesView(verticesBuffer, positionElement); gpu::BufferView normalsView(verticesBuffer, normalElement); gpu::BufferView colorView(colorBuffer, colorElement); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(NORMALS_SLOT, normalsView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.setIndexBuffer(gpu::UINT16, indicesBuffer, 0); if (solid) { batch.drawIndexed(gpu::TRIANGLES, indices); } else { batch.drawIndexed(gpu::LINES, indices); }} void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) { IntPair key(xDivisions, yDivisions); Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions)); int vertices = (xDivisions + 1 + yDivisions + 1) * 2; if (!_gridBuffers.contains(key)) { auto verticesBuffer = std::make_shared<gpu::Buffer>(); GLfloat* vertexData = new GLfloat[vertices * 2]; GLfloat* vertex = vertexData; for (int i = 0; i <= xDivisions; i++) { float x = (float)i / xDivisions; *(vertex++) = x; *(vertex++) = 0.0f; *(vertex++) = x; *(vertex++) = 1.0f; } for (int i = 0; i <= yDivisions; i++) { float y = (float)i / yDivisions; *(vertex++) = 0.0f; *(vertex++) = y; *(vertex++) = 1.0f; *(vertex++) = y; } verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData); delete[] vertexData; _gridBuffers[key] = verticesBuffer; } if (!_gridColors.contains(colorKey)) { auto colorBuffer = std::make_shared<gpu::Buffer>(); _gridColors[colorKey] = colorBuffer; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; } gpu::BufferPointer verticesBuffer = _gridBuffers[key]; gpu::BufferPointer colorBuffer = _gridColors[colorKey]; const int VERTICES_SLOT = 0; const int COLOR_SLOT = 1; auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.draw(gpu::LINES, vertices, 0);} // TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that??void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) { #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderGrid(x["<<x<<"], " "y["<<y<<"]," "w["<<width<<"]," "h["<<height<<"]," "rows["<<rows<<"]," "cols["<<cols<<"]," " id:"<<id<<")..."; #endif bool registered = (id != UNKNOWN_ID); Vec3Pair key(glm::vec3(x, y, width), glm::vec3(height, rows, cols)); Vec3Pair colorKey(glm::vec3(color.x, color.y, rows), glm::vec3(color.z, color.y, cols)); int vertices = (cols + 1 + rows + 1) * 2; if ((registered && (!_registeredAlternateGridBuffers.contains(id) || _lastRegisteredAlternateGridBuffers[id] != key)) || (!registered && !_alternateGridBuffers.contains(key))) { if (registered && _registeredAlternateGridBuffers.contains(id)) { _registeredAlternateGridBuffers[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderGrid()... RELEASING REGISTERED VERTICES BUFFER"; #endif } auto verticesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredAlternateGridBuffers[id] = verticesBuffer; _lastRegisteredAlternateGridBuffers[id] = key; } else { _alternateGridBuffers[key] = verticesBuffer; } GLfloat* vertexData = new GLfloat[vertices * 2]; GLfloat* vertex = vertexData; int dx = width / cols; int dy = height / rows; int tx = x; int ty = y; // Draw horizontal grid lines for (int i = rows + 1; --i >= 0; ) { *(vertex++) = x; *(vertex++) = ty; *(vertex++) = x + width; *(vertex++) = ty; ty += dy; } // Draw vertical grid lines for (int i = cols + 1; --i >= 0; ) { *(vertex++) = tx; *(vertex++) = y; *(vertex++) = tx; *(vertex++) = y + height; tx += dx; } verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData); delete[] vertexData; } if (!_gridColors.contains(colorKey)) { auto colorBuffer = std::make_shared<gpu::Buffer>(); _gridColors[colorKey] = colorBuffer; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; } gpu::BufferPointer verticesBuffer = registered ? _registeredAlternateGridBuffers[id] : _alternateGridBuffers[key]; gpu::BufferPointer colorBuffer = _gridColors[colorKey]; const int VERTICES_SLOT = 0; const int COLOR_SLOT = 1; auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.draw(gpu::LINES, vertices, 0);} void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) { BatchItemDetails& details = _registeredVertices[id]; if (details.isCreated) { details.clear(); #ifdef WANT_DEBUG qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; #endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2; details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared<gpu::Buffer>(); auto colorBuffer = std::make_shared<gpu::Buffer>();Lines 1–500 of 2247. Load more
// // GeometryCache.cpp // interface/src/renderer // // Created by Andrzej Kapolka on 6/21/13. // Copyright 2013 High Fidelity, Inc. // // Distributed under the Apache License, Version 2.0. // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // // include this before QOpenGLBuffer, which includes an earlier version of OpenGL #include <cmath> #include <QNetworkReply> #include <QRunnable> #include <QThreadPool> #include <gpu/Batch.h> #include <gpu/GLBackend.h> #include <FSTReader.h> #include <NumericalConstants.h> #include "TextureCache.h" #include "RenderUtilsLogging.h" #include "GeometryCache.h" #include "standardTransformPNTC_vert.h" #include "standardDrawTexture_frag.h" #include "gpu/StandardShaderLib.h" //#define WANT_DEBUG const int GeometryCache::UNKNOWN_ID = -1; GeometryCache::GeometryCache() : _nextID(0) { const qint64 GEOMETRY_DEFAULT_UNUSED_MAX_SIZE = DEFAULT_UNUSED_MAX_SIZE; setUnusedResourceCacheSize(GEOMETRY_DEFAULT_UNUSED_MAX_SIZE); } GeometryCache::~GeometryCache() { #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::~GeometryCache()... "; qCDebug(renderutils) << " _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size(); qCDebug(renderutils) << " _line3DVBOs.size():" << _line3DVBOs.size(); qCDebug(renderutils) << " BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population; #endif //def WANT_DEBUG } const int NUM_VERTICES_PER_TRIANGLE = 3; const int NUM_TRIANGLES_PER_QUAD = 2; const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD; const int NUM_COORDS_PER_VERTEX = 3; void GeometryCache::renderSphere(gpu::Batch& batch, float radius, int slices, int stacks, const glm::vec4& color, bool solid, int id) { bool registered = (id != UNKNOWN_ID); Vec2Pair radiusKey(glm::vec2(radius, slices), glm::vec2(stacks, 0)); IntPair slicesStacksKey(slices, stacks); Vec3Pair colorKey(glm::vec3(color.x, color.y, slices), glm::vec3(color.z, color.w, stacks)); int vertices = slices * (stacks - 1) + 2; int indices = slices * (stacks - 1) * NUM_VERTICES_PER_TRIANGULATED_QUAD; if ((registered && (!_registeredSphereVertices.contains(id) || _lastRegisteredSphereVertices[id] != radiusKey)) || (!registered && !_sphereVertices.contains(radiusKey))) { if (registered && _registeredSphereVertices.contains(id)) { _registeredSphereVertices[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED VERTICES BUFFER"; #endif } auto verticesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereVertices[id] = verticesBuffer; _lastRegisteredSphereVertices[id] = radiusKey; } else { _sphereVertices[radiusKey] = verticesBuffer; } GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX]; GLfloat* vertex = vertexData; // south pole *(vertex++) = 0.0f; *(vertex++) = 0.0f; *(vertex++) = -1.0f * radius; //add stacks vertices climbing up Y axis for (int i = 1; i < stacks; i++) { float phi = PI * (float)i / (float)(stacks) - PI_OVER_TWO; float z = sinf(phi) * radius; float stackRadius = cosf(phi) * radius; for (int j = 0; j < slices; j++) { float theta = TWO_PI * (float)j / (float)slices; *(vertex++) = sinf(theta) * stackRadius; *(vertex++) = cosf(theta) * stackRadius; *(vertex++) = z; } } // north pole *(vertex++) = 0.0f; *(vertex++) = 0.0f; *(vertex++) = 1.0f * radius; verticesBuffer->append(sizeof(GLfloat) * vertices * NUM_COORDS_PER_VERTEX, (gpu::Byte*) vertexData); delete[] vertexData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING VERTICES BUFFER"; qCDebug(renderutils) << " radius:" << radius; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << " _sphereVertices.size():" << _sphereVertices.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED VERTICES BUFFER"; } #endif if ((registered && (!_registeredSphereIndices.contains(id) || _lastRegisteredSphereIndices[id] != slicesStacksKey)) || (!registered && !_sphereIndices.contains(slicesStacksKey))) { if (registered && _registeredSphereIndices.contains(id)) { _registeredSphereIndices[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED INDICES BUFFER"; #endif } auto indicesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereIndices[id] = indicesBuffer; _lastRegisteredSphereIndices[id] = slicesStacksKey; } else { _sphereIndices[slicesStacksKey] = indicesBuffer; } GLushort* indexData = new GLushort[indices]; GLushort* index = indexData; int indexCount = 0; // South cap GLushort bottom = 0; GLushort top = 1; for (int i = 0; i < slices; i++) { *(index++) = bottom; *(index++) = top + i; *(index++) = top + (i + 1) % slices; indexCount += 3; } // (stacks - 2) ribbons for (int i = 0; i < stacks - 2; i++) { bottom = i * slices + 1; top = bottom + slices; for (int j = 0; j < slices; j++) { int next = (j + 1) % slices; *(index++) = top + next; *(index++) = bottom + j; *(index++) = top + j; indexCount += 3; *(index++) = bottom + next; *(index++) = bottom + j; *(index++) = top + next; indexCount += 3; } } // north cap bottom = (stacks - 2) * slices + 1; top = bottom + slices; for (int i = 0; i < slices; i++) { *(index++) = bottom + (i + 1) % slices; *(index++) = bottom + i; *(index++) = top; indexCount += 3; } indicesBuffer->append(sizeof(GLushort) * indices, (gpu::Byte*) indexData); delete[] indexData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING INDICES BUFFER"; qCDebug(renderutils) << " radius:" << radius; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << "indexCount:" << indexCount; qCDebug(renderutils) << " indices:" << indices; qCDebug(renderutils) << " _sphereIndices.size():" << _sphereIndices.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED INDICES BUFFER"; } #endif if ((registered && (!_registeredSphereColors.contains(id) || _lastRegisteredSphereColors[id] != colorKey)) || (!registered && !_sphereColors.contains(colorKey))) { if (registered && _registeredSphereColors.contains(id)) { _registeredSphereColors[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderSphere()... RELEASING REGISTERED COLORS BUFFER"; #endif } auto colorBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredSphereColors[id] = colorBuffer; _lastRegisteredSphereColors[id] = colorKey; } else { _sphereColors[colorKey] = colorBuffer; } int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderSphere()... --- CREATING COLORS BUFFER"; qCDebug(renderutils) << " vertices:" << vertices; qCDebug(renderutils) << " color:" << color; qCDebug(renderutils) << " slices:" << slices; qCDebug(renderutils) << " stacks:" << stacks; qCDebug(renderutils) << " _sphereColors.size():" << _sphereColors.size(); #endif } #ifdef WANT_DEBUG else if (registered) { qCDebug(renderutils) << "renderSphere()... REUSING PREVIOUSLY REGISTERED COLORS BUFFER"; } #endif gpu::BufferPointer verticesBuffer = registered ? _registeredSphereVertices[id] : _sphereVertices[radiusKey]; gpu::BufferPointer indicesBuffer = registered ? _registeredSphereIndices[id] : _sphereIndices[slicesStacksKey]; gpu::BufferPointer colorBuffer = registered ? _registeredSphereColors[id] : _sphereColors[colorKey]; const int VERTICES_SLOT = 0; const int NORMALS_SLOT = 1; const int COLOR_SLOT = 2; static gpu::Stream::FormatPointer streamFormat; static gpu::Element positionElement, normalElement, colorElement; if (!streamFormat) { streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::NORMAL, NORMALS_SLOT, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ)); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); positionElement = streamFormat->getAttributes().at(gpu::Stream::POSITION)._element; normalElement = streamFormat->getAttributes().at(gpu::Stream::NORMAL)._element; colorElement = streamFormat->getAttributes().at(gpu::Stream::COLOR)._element; } gpu::BufferView verticesView(verticesBuffer, positionElement); gpu::BufferView normalsView(verticesBuffer, normalElement); gpu::BufferView colorView(colorBuffer, colorElement); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(NORMALS_SLOT, normalsView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.setIndexBuffer(gpu::UINT16, indicesBuffer, 0); if (solid) { batch.drawIndexed(gpu::TRIANGLES, indices); } else { batch.drawIndexed(gpu::LINES, indices); } } void GeometryCache::renderGrid(gpu::Batch& batch, int xDivisions, int yDivisions, const glm::vec4& color) { IntPair key(xDivisions, yDivisions); Vec3Pair colorKey(glm::vec3(color.x, color.y, yDivisions), glm::vec3(color.z, color.y, xDivisions)); int vertices = (xDivisions + 1 + yDivisions + 1) * 2; if (!_gridBuffers.contains(key)) { auto verticesBuffer = std::make_shared<gpu::Buffer>(); GLfloat* vertexData = new GLfloat[vertices * 2]; GLfloat* vertex = vertexData; for (int i = 0; i <= xDivisions; i++) { float x = (float)i / xDivisions; *(vertex++) = x; *(vertex++) = 0.0f; *(vertex++) = x; *(vertex++) = 1.0f; } for (int i = 0; i <= yDivisions; i++) { float y = (float)i / yDivisions; *(vertex++) = 0.0f; *(vertex++) = y; *(vertex++) = 1.0f; *(vertex++) = y; } verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData); delete[] vertexData; _gridBuffers[key] = verticesBuffer; } if (!_gridColors.contains(colorKey)) { auto colorBuffer = std::make_shared<gpu::Buffer>(); _gridColors[colorKey] = colorBuffer; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; } gpu::BufferPointer verticesBuffer = _gridBuffers[key]; gpu::BufferPointer colorBuffer = _gridColors[colorKey]; const int VERTICES_SLOT = 0; const int COLOR_SLOT = 1; auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.draw(gpu::LINES, vertices, 0); } // TODO: why do we seem to create extra BatchItemDetails when we resize the window?? what's that?? void GeometryCache::renderGrid(gpu::Batch& batch, int x, int y, int width, int height, int rows, int cols, const glm::vec4& color, int id) { #ifdef WANT_DEBUG qCDebug(renderutils) << "GeometryCache::renderGrid(x["<<x<<"], " "y["<<y<<"]," "w["<<width<<"]," "h["<<height<<"]," "rows["<<rows<<"]," "cols["<<cols<<"]," " id:"<<id<<")..."; #endif bool registered = (id != UNKNOWN_ID); Vec3Pair key(glm::vec3(x, y, width), glm::vec3(height, rows, cols)); Vec3Pair colorKey(glm::vec3(color.x, color.y, rows), glm::vec3(color.z, color.y, cols)); int vertices = (cols + 1 + rows + 1) * 2; if ((registered && (!_registeredAlternateGridBuffers.contains(id) || _lastRegisteredAlternateGridBuffers[id] != key)) || (!registered && !_alternateGridBuffers.contains(key))) { if (registered && _registeredAlternateGridBuffers.contains(id)) { _registeredAlternateGridBuffers[id].reset(); #ifdef WANT_DEBUG qCDebug(renderutils) << "renderGrid()... RELEASING REGISTERED VERTICES BUFFER"; #endif } auto verticesBuffer = std::make_shared<gpu::Buffer>(); if (registered) { _registeredAlternateGridBuffers[id] = verticesBuffer; _lastRegisteredAlternateGridBuffers[id] = key; } else { _alternateGridBuffers[key] = verticesBuffer; } GLfloat* vertexData = new GLfloat[vertices * 2]; GLfloat* vertex = vertexData; int dx = width / cols; int dy = height / rows; int tx = x; int ty = y; // Draw horizontal grid lines for (int i = rows + 1; --i >= 0; ) { *(vertex++) = x; *(vertex++) = ty; *(vertex++) = x + width; *(vertex++) = ty; ty += dy; } // Draw vertical grid lines for (int i = cols + 1; --i >= 0; ) { *(vertex++) = tx; *(vertex++) = y; *(vertex++) = tx; *(vertex++) = y + height; tx += dx; } verticesBuffer->append(sizeof(GLfloat) * vertices * 2, (gpu::Byte*) vertexData); delete[] vertexData; } if (!_gridColors.contains(colorKey)) { auto colorBuffer = std::make_shared<gpu::Buffer>(); _gridColors[colorKey] = colorBuffer; int compactColor = ((int(color.x * 255.0f) & 0xFF)) | ((int(color.y * 255.0f) & 0xFF) << 8) | ((int(color.z * 255.0f) & 0xFF) << 16) | ((int(color.w * 255.0f) & 0xFF) << 24); int* colorData = new int[vertices]; int* colorDataAt = colorData; for(int v = 0; v < vertices; v++) { *(colorDataAt++) = compactColor; } colorBuffer->append(sizeof(int) * vertices, (gpu::Byte*) colorData); delete[] colorData; } gpu::BufferPointer verticesBuffer = registered ? _registeredAlternateGridBuffers[id] : _alternateGridBuffers[key]; gpu::BufferPointer colorBuffer = _gridColors[colorKey]; const int VERTICES_SLOT = 0; const int COLOR_SLOT = 1; auto streamFormat = std::make_shared<gpu::Stream::Format>(); // 1 for everyone streamFormat->setAttribute(gpu::Stream::POSITION, VERTICES_SLOT, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::XYZ), 0); streamFormat->setAttribute(gpu::Stream::COLOR, COLOR_SLOT, gpu::Element(gpu::VEC4, gpu::UINT8, gpu::RGBA)); gpu::BufferView verticesView(verticesBuffer, 0, verticesBuffer->getSize(), streamFormat->getAttributes().at(gpu::Stream::POSITION)._element); gpu::BufferView colorView(colorBuffer, streamFormat->getAttributes().at(gpu::Stream::COLOR)._element); batch.setInputFormat(streamFormat); batch.setInputBuffer(VERTICES_SLOT, verticesView); batch.setInputBuffer(COLOR_SLOT, colorView); batch.draw(gpu::LINES, vertices, 0); } void GeometryCache::updateVertices(int id, const QVector<glm::vec2>& points, const glm::vec4& color) { BatchItemDetails& details = _registeredVertices[id]; if (details.isCreated) { details.clear(); #ifdef WANT_DEBUG qCDebug(renderutils) << "updateVertices()... RELEASING REGISTERED"; #endif // def WANT_DEBUG } const int FLOATS_PER_VERTEX = 2; details.isCreated = true; details.vertices = points.size(); details.vertexSize = FLOATS_PER_VERTEX; auto verticesBuffer = std::make_shared<gpu::Buffer>(); auto colorBuffer = std::make_shared<gpu::Buffer>();