2247 lines · 98.4 KB · C++
RawDownload
////  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.