Andrew Meadowsremove unused variable4bf99fe9 years agoHistory
2228 lines · 91.5 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 "GeometryCache.h" #include <qmath.h>#include <cmath> #include <QtCore/QThreadPool>#include <QtCore/QFileInfo>#include <QtNetwork/QNetworkReply> #include <shared/Shapes.h>#include <shared/PlatformHacks.h> #include <FSTReader.h>#include <NumericalConstants.h> #include "TextureCache.h"#include "RenderUtilsLogging.h"#include "StencilMaskPass.h"#include "FadeEffect.h" #include "gpu/StandardShaderLib.h" #include "model/TextureMap.h"#include "render/Args.h" #include "standardTransformPNTC_vert.h"#include "standardDrawTexture_frag.h" #include "simple_vert.h"#include "simple_textured_frag.h"#include "simple_textured_unlit_frag.h"#include "simple_fade_vert.h"#include "simple_textured_fade_frag.h"#include "simple_textured_unlit_fade_frag.h"#include "simple_opaque_web_browser_frag.h"#include "simple_transparent_web_browser_frag.h"#include "glowLine_vert.h"#include "glowLine_frag.h" #include "grid_frag.h" //#define WANT_DEBUG const int GeometryCache::UNKNOWN_ID = -1;  static const int VERTICES_PER_TRIANGLE = 3; static const gpu::Element POSITION_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };static const gpu::Element NORMAL_ELEMENT { gpu::VEC3, gpu::FLOAT, gpu::XYZ };static const gpu::Element COLOR_ELEMENT { gpu::VEC4, gpu::NUINT8, gpu::RGBA };static const gpu::Element TEXCOORD4_ELEMENT { gpu::VEC4, gpu::FLOAT, gpu::XYZW }; static gpu::Stream::FormatPointer SOLID_STREAM_FORMAT;static gpu::Stream::FormatPointer INSTANCED_SOLID_STREAM_FORMAT;static gpu::Stream::FormatPointer INSTANCED_SOLID_FADE_STREAM_FORMAT; static const uint SHAPE_VERTEX_STRIDE = sizeof(glm::vec3) * 2; // vertices and normalsstatic const uint SHAPE_NORMALS_OFFSET = sizeof(glm::vec3);static const gpu::Type SHAPE_INDEX_TYPE = gpu::UINT32; template <size_t SIDES>std::vector<vec3> polygon() {    std::vector<vec3> result;    result.reserve(SIDES);    double angleIncrement = 2.0 * M_PI / SIDES;    for (size_t i = 0; i < SIDES; i++) {        double angle = (double)i * angleIncrement;        result.push_back(vec3{ cos(angle) * 0.5, 0.0, sin(angle) * 0.5 });    }    return result;} void GeometryCache::ShapeData::setupVertices(gpu::BufferPointer& vertexBuffer, const geometry::VertexVector& vertices) {    gpu::Buffer::Size offset = vertexBuffer->getSize();    vertexBuffer->append(vertices);     gpu::Buffer::Size viewSize = vertices.size() * 2 * sizeof(glm::vec3);     _positionView = gpu::BufferView(vertexBuffer, offset,        viewSize, SHAPE_VERTEX_STRIDE, POSITION_ELEMENT);    _normalView = gpu::BufferView(vertexBuffer, offset + SHAPE_NORMALS_OFFSET,        viewSize, SHAPE_VERTEX_STRIDE, NORMAL_ELEMENT);} void GeometryCache::ShapeData::setupIndices(gpu::BufferPointer& indexBuffer, const geometry::IndexVector& indices, const geometry::IndexVector& wireIndices) {    gpu::Buffer::Size offset = indexBuffer->getSize();    if (!indices.empty()) {        for (uint32_t i = 0; i < indices.size(); ++i) {            indexBuffer->append((uint16_t)indices[i]);        }    }    gpu::Size viewSize = indices.size() * sizeof(uint16_t);    _indicesView = gpu::BufferView(indexBuffer, offset, viewSize, gpu::Element::INDEX_UINT16);     offset = indexBuffer->getSize();    if (!wireIndices.empty()) {        for (uint32_t i = 0; i < wireIndices.size(); ++i) {            indexBuffer->append((uint16_t)wireIndices[i]);        }    }    viewSize = wireIndices.size() * sizeof(uint16_t);    _wireIndicesView = gpu::BufferView(indexBuffer, offset, viewSize, gpu::Element::INDEX_UINT16);} void GeometryCache::ShapeData::setupBatch(gpu::Batch& batch) const {    batch.setInputBuffer(gpu::Stream::POSITION, _positionView);    batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);    batch.setIndexBuffer(_indicesView);} void GeometryCache::ShapeData::draw(gpu::Batch& batch) const {    gpu::Buffer::Size numIndices = _indicesView.getNumElements();    if (numIndices > 0) {        setupBatch(batch);        batch.drawIndexed(gpu::TRIANGLES, numIndices, 0);    }} void GeometryCache::ShapeData::drawWire(gpu::Batch& batch) const {    gpu::Buffer::Size numIndices = _wireIndicesView.getNumElements();    if (numIndices > 0) {        batch.setInputBuffer(gpu::Stream::POSITION, _positionView);        batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);        batch.setIndexBuffer(_wireIndicesView);        batch.drawIndexed(gpu::LINES, numIndices, 0);    }} void GeometryCache::ShapeData::drawInstances(gpu::Batch& batch, size_t count) const {    gpu::Buffer::Size numIndices = _indicesView.getNumElements();    if (numIndices > 0) {        setupBatch(batch);        batch.drawIndexedInstanced((gpu::uint32)count, gpu::TRIANGLES, numIndices, 0);    }} void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count) const {    gpu::Buffer::Size numIndices = _wireIndicesView.getNumElements();    if (numIndices > 0) {        batch.setInputBuffer(gpu::Stream::POSITION, _positionView);        batch.setInputBuffer(gpu::Stream::NORMAL, _normalView);        batch.setIndexBuffer(_wireIndicesView);        batch.drawIndexedInstanced((gpu::uint32)count, gpu::LINES, numIndices, 0);    }} static const size_t ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT = 3; size_t GeometryCache::getShapeTriangleCount(Shape shape) {    return _shapes[shape]._indicesView.getNumElements() / VERTICES_PER_TRIANGLE;} size_t GeometryCache::getSphereTriangleCount() {    return getShapeTriangleCount(Sphere);} size_t GeometryCache::getCubeTriangleCount() {    return getShapeTriangleCount(Cube);} using IndexPair = uint64_t;using IndexPairs = std::unordered_set<IndexPair>; static IndexPair indexToken(geometry::Index a, geometry::Index b) {    if (a > b) {        std::swap(a, b);    }    return (((IndexPair)a) << 32) | ((IndexPair)b);} template <size_t N>void setupFlatShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {    using namespace geometry;    VertexVector vertices;    IndexVector solidIndices, wireIndices;    IndexPairs wireSeenIndices;     size_t faceCount = shape.faces.size();    size_t faceIndexCount = triangulatedFaceIndexCount<N>();     vertices.reserve(N * faceCount * 2);    solidIndices.reserve(faceIndexCount * faceCount);     Index baseVertex = 0;    for (size_t f = 0; f < faceCount; f++) {        const Face<N>& face = shape.faces[f];        // Compute the face normal        vec3 faceNormal = shape.getFaceNormal(f);         // Create the vertices for the face        for (Index i = 0; i < N; i++) {            Index originalIndex = face[i];            vertices.push_back(shape.vertices[originalIndex]);            vertices.push_back(faceNormal);        }         // Create the wire indices for unseen edges        for (Index i = 0; i < N; i++) {            Index a = i;            Index b = (i + 1) % N;            auto token = indexToken(face[a], face[b]);            if (0 == wireSeenIndices.count(token)) {                wireSeenIndices.insert(token);                wireIndices.push_back(a + baseVertex);                wireIndices.push_back(b + baseVertex);            }        }         // Create the solid face indices        for (Index i = 0; i < N - 2; i++) {            solidIndices.push_back(0 + baseVertex);            solidIndices.push_back(i + 1 + baseVertex);            solidIndices.push_back(i + 2 + baseVertex);        }        baseVertex += (Index)N;    }     shapeData.setupVertices(vertexBuffer, vertices);    shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);} template <size_t N>void setupSmoothShape(GeometryCache::ShapeData& shapeData, const geometry::Solid<N>& shape, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {    using namespace geometry;     VertexVector vertices;    vertices.reserve(shape.vertices.size() * 2);    for (const auto& vertex : shape.vertices) {        vertices.push_back(vertex);        vertices.push_back(vertex);    }     IndexVector solidIndices, wireIndices;    IndexPairs wireSeenIndices;     size_t faceCount = shape.faces.size();    size_t faceIndexCount = triangulatedFaceIndexCount<N>();     solidIndices.reserve(faceIndexCount * faceCount);     Index baseVertex = 0;    for (size_t f = 0; f < faceCount; f++) {        const Face<N>& face = shape.faces[f];        // Create the wire indices for unseen edges        for (Index i = 0; i < N; i++) {            Index a = face[i];            Index b = face[(i + 1) % N];            auto token = indexToken(a, b);            if (0 == wireSeenIndices.count(token)) {                wireSeenIndices.insert(token);                wireIndices.push_back(a + baseVertex);                wireIndices.push_back(b + baseVertex);            }        }         // Create the solid face indices        for (Index i = 0; i < N - 2; i++) {            solidIndices.push_back(face[i] + baseVertex);            solidIndices.push_back(face[i + 1] + baseVertex);            solidIndices.push_back(face[i + 2] + baseVertex);        }    }     shapeData.setupVertices(vertexBuffer, vertices);    shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);} template <uint32_t N>void extrudePolygon(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer, bool isConical = false) {    using namespace geometry;    VertexVector vertices;    IndexVector solidIndices, wireIndices;     // Top (if not conical) and bottom faces    std::vector<vec3> shape = polygon<N>();    if (isConical) {        for (uint32_t i = 0; i < N; i++) {            vertices.push_back(vec3(0.0f, 0.5f, 0.0f));            vertices.push_back(vec3(0.0f, 1.0f, 0.0f));        }    } else {        for (const vec3& v : shape) {            vertices.push_back(vec3(v.x, 0.5f, v.z));            vertices.push_back(vec3(0.0f, 1.0f, 0.0f));        }    }    for (const vec3& v : shape) {        vertices.push_back(vec3(v.x, -0.5f, v.z));        vertices.push_back(vec3(0.0f, -1.0f, 0.0f));    }    Index baseVertex = 0;    for (uint32_t i = 2; i < N; i++) {        solidIndices.push_back(baseVertex + 0);        solidIndices.push_back(baseVertex + i);        solidIndices.push_back(baseVertex + i - 1);        solidIndices.push_back(baseVertex + N);        solidIndices.push_back(baseVertex + i + N - 1);        solidIndices.push_back(baseVertex + i + N);    }    for (uint32_t i = 1; i <= N; i++) {        wireIndices.push_back(baseVertex + (i % N));        wireIndices.push_back(baseVertex + i - 1);        wireIndices.push_back(baseVertex + (i % N) + N);        wireIndices.push_back(baseVertex + (i - 1) + N);    }     // Now do the sides    baseVertex += 2 * N;     for (uint32_t i = 0; i < N; i++) {        vec3 left = shape[i];        vec3 right = shape[(i + 1) % N];        vec3 normal = glm::normalize(left + right);        vec3 topLeft = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(left.x, 0.5f, left.z));        vec3 topRight = (isConical ? vec3(0.0f, 0.5f, 0.0f) : vec3(right.x, 0.5f, right.z));        vec3 bottomLeft = vec3(left.x, -0.5f, left.z);        vec3 bottomRight = vec3(right.x, -0.5f, right.z);         vertices.push_back(topLeft);        vertices.push_back(normal);        vertices.push_back(bottomLeft);        vertices.push_back(normal);        vertices.push_back(topRight);        vertices.push_back(normal);        vertices.push_back(bottomRight);        vertices.push_back(normal);         solidIndices.push_back(baseVertex + 0);        solidIndices.push_back(baseVertex + 2);        solidIndices.push_back(baseVertex + 1);        solidIndices.push_back(baseVertex + 1);        solidIndices.push_back(baseVertex + 2);        solidIndices.push_back(baseVertex + 3);        wireIndices.push_back(baseVertex + 0);        wireIndices.push_back(baseVertex + 1);        wireIndices.push_back(baseVertex + 3);        wireIndices.push_back(baseVertex + 2);        baseVertex += 4;    }     shapeData.setupVertices(vertexBuffer, vertices);    shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);} void drawCircle(GeometryCache::ShapeData& shapeData, gpu::BufferPointer& vertexBuffer, gpu::BufferPointer& indexBuffer) {    // Draw a circle with radius 1/4th the size of the bounding box    using namespace geometry;     VertexVector vertices;    IndexVector solidIndices, wireIndices;    const int NUM_CIRCLE_VERTICES = 64;     std::vector<vec3> shape = polygon<NUM_CIRCLE_VERTICES>();    for (const vec3& v : shape) {        vertices.push_back(vec3(v.x, 0.0f, v.z));        vertices.push_back(vec3(0.0f, 0.0f, 0.0f));    }     Index baseVertex = 0;    for (uint32_t i = 2; i < NUM_CIRCLE_VERTICES; i++) {        solidIndices.push_back(baseVertex + 0);        solidIndices.push_back(baseVertex + i);        solidIndices.push_back(baseVertex + i - 1);        solidIndices.push_back(baseVertex + NUM_CIRCLE_VERTICES);        solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES - 1);        solidIndices.push_back(baseVertex + i + NUM_CIRCLE_VERTICES);    }     for (uint32_t i = 1; i <= NUM_CIRCLE_VERTICES; i++) {        wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES));        wireIndices.push_back(baseVertex + i - 1);        wireIndices.push_back(baseVertex + (i % NUM_CIRCLE_VERTICES) + NUM_CIRCLE_VERTICES);        wireIndices.push_back(baseVertex + (i - 1) + NUM_CIRCLE_VERTICES);    }     shapeData.setupVertices(vertexBuffer, vertices);    shapeData.setupIndices(indexBuffer, solidIndices, wireIndices);} // FIXME solids need per-face vertices, but smooth shaded// components do not.  Find a way to support using draw elements// or draw arrays as appropriate// Maybe special case cone and cylinder since they combine flat// and smooth shadingvoid GeometryCache::buildShapes() {    using namespace geometry;    auto vertexBuffer = std::make_shared<gpu::Buffer>();    auto indexBuffer = std::make_shared<gpu::Buffer>();    // Cube     setupFlatShape(_shapes[Cube], geometry::cube(), _shapeVertices, _shapeIndices);    // Tetrahedron    setupFlatShape(_shapes[Tetrahedron], geometry::tetrahedron(), _shapeVertices, _shapeIndices);    // Icosahedron    setupFlatShape(_shapes[Icosahedron], geometry::icosahedron(), _shapeVertices, _shapeIndices);    // Octahedron    setupFlatShape(_shapes[Octahedron], geometry::octahedron(), _shapeVertices, _shapeIndices);    // Dodecahedron    setupFlatShape(_shapes[Dodecahedron], geometry::dodecahedron(), _shapeVertices, _shapeIndices);     // Sphere    // FIXME this uses way more vertices than required.  Should find a way to calculate the indices    // using shared vertices for better vertex caching    auto sphere = geometry::tesselate(geometry::icosahedron(), ICOSAHEDRON_TO_SPHERE_TESSELATION_COUNT);    sphere.fitDimension(1.0f);    setupSmoothShape(_shapes[Sphere], sphere, _shapeVertices, _shapeIndices);     // Line    {        ShapeData& shapeData = _shapes[Line];        shapeData.setupVertices(_shapeVertices, VertexVector {            vec3(-0.5f, 0.0f, 0.0f), vec3(-0.5f, 0.0f, 0.0f),            vec3(0.5f, 0.0f, 0.0f), vec3(0.5f, 0.0f, 0.0f)        });        IndexVector wireIndices;        // Only two indices        wireIndices.push_back(0);        wireIndices.push_back(1);        shapeData.setupIndices(_shapeIndices, IndexVector(), wireIndices);    }     //Triangle,    extrudePolygon<3>(_shapes[Triangle], _shapeVertices, _shapeIndices);    //Hexagon,    extrudePolygon<6>(_shapes[Hexagon], _shapeVertices, _shapeIndices);    //Octagon,    extrudePolygon<8>(_shapes[Octagon], _shapeVertices, _shapeIndices);    //Cylinder,    extrudePolygon<64>(_shapes[Cylinder], _shapeVertices, _shapeIndices);    //Cone,    extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true);    //Circle    drawCircle(_shapes[Circle], _shapeVertices, _shapeIndices);    // Not implememented yet:    //Quad,    //Torus,  } gpu::Stream::FormatPointer& getSolidStreamFormat() {    if (!SOLID_STREAM_FORMAT) {        SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone        SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);        SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);    }    return SOLID_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedSolidStreamFormat() {    if (!INSTANCED_SOLID_STREAM_FORMAT) {        INSTANCED_SOLID_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone        INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);        INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);        INSTANCED_SOLID_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);    }    return INSTANCED_SOLID_STREAM_FORMAT;} gpu::Stream::FormatPointer& getInstancedSolidFadeStreamFormat() {    if (!INSTANCED_SOLID_FADE_STREAM_FORMAT) {        INSTANCED_SOLID_FADE_STREAM_FORMAT = std::make_shared<gpu::Stream::Format>(); // 1 for everyone        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::POSITION, gpu::Stream::POSITION, POSITION_ELEMENT);        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::NORMAL, gpu::Stream::NORMAL, NORMAL_ELEMENT);        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD2, gpu::Stream::TEXCOORD2, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD3, gpu::Stream::TEXCOORD3, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);        INSTANCED_SOLID_FADE_STREAM_FORMAT->setAttribute(gpu::Stream::TEXCOORD4, gpu::Stream::TEXCOORD4, TEXCOORD4_ELEMENT, 0, gpu::Stream::PER_INSTANCE);    }    return INSTANCED_SOLID_FADE_STREAM_FORMAT;} QHash<SimpleProgramKey, gpu::PipelinePointer> GeometryCache::_simplePrograms; gpu::ShaderPointer GeometryCache::_simpleShader;gpu::ShaderPointer GeometryCache::_unlitShader;gpu::ShaderPointer GeometryCache::_simpleFadeShader;gpu::ShaderPointer GeometryCache::_unlitFadeShader; render::ShapePipelinePointer GeometryCache::_simpleOpaquePipeline;render::ShapePipelinePointer GeometryCache::_simpleTransparentPipeline;render::ShapePipelinePointer GeometryCache::_simpleOpaqueFadePipeline;render::ShapePipelinePointer GeometryCache::_simpleTransparentFadePipeline;render::ShapePipelinePointer GeometryCache::_simpleWirePipeline; uint8_t GeometryCache::CUSTOM_PIPELINE_NUMBER = 0; render::ShapePipelinePointer GeometryCache::shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key) {    initializeShapePipelines(); 

Lines 1–500 of 2228.