2214 lines · 89.6 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 <gpu/GPUConfig.h> #include <cmath> #include <QNetworkReply>#include <QRunnable>#include <QThreadPool> #include <gpu/Batch.h>#include <gpu/GLBackend.h> #include <SharedUtil.h> #include "TextureCache.h"#include "GeometryCache.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() {    foreach (const VerticesIndices& vbo, _hemisphereVBOs) {        glDeleteBuffers(1, &vbo.first);        glDeleteBuffers(1, &vbo.second);    }    qDebug() << "GeometryCache::~GeometryCache()... ";    qDebug() << "    _registeredLine3DVBOs.size():" << _registeredLine3DVBOs.size();    qDebug() << "    _line3DVBOs.size():" << _line3DVBOs.size();    qDebug() << "    BatchItemDetails... population:" << GeometryCache::BatchItemDetails::population;} void GeometryCache::renderHemisphere(int slices, int stacks) {    VerticesIndices& vbo = _hemisphereVBOs[IntPair(slices, stacks)];    int vertices = slices * (stacks - 1) + 1;    int indices = slices * 2 * 3 * (stacks - 2) + slices * 3;    if (vbo.first == 0) {            GLfloat* vertexData = new GLfloat[vertices * 3];        GLfloat* vertex = vertexData;        for (int i = 0; i < stacks - 1; i++) {            float phi = PI_OVER_TWO * (float)i / (float)(stacks - 1);            float z = sinf(phi), radius = cosf(phi);                        for (int j = 0; j < slices; j++) {                float theta = TWO_PI * (float)j / (float)slices;                 *(vertex++) = sinf(theta) * radius;                *(vertex++) = cosf(theta) * radius;                *(vertex++) = z;            }        }        *(vertex++) = 0.0f;        *(vertex++) = 0.0f;        *(vertex++) = 1.0f;                glGenBuffers(1, &vbo.first);        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);        glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);        delete[] vertexData;                GLushort* indexData = new GLushort[indices];        GLushort* index = indexData;        for (int i = 0; i < stacks - 2; i++) {            GLushort bottom = i * slices;            GLushort top = bottom + slices;            for (int j = 0; j < slices; j++) {                int next = (j + 1) % slices;                                *(index++) = bottom + j;                *(index++) = top + next;                *(index++) = top + j;                                *(index++) = bottom + j;                *(index++) = bottom + next;                *(index++) = top + next;            }        }        GLushort bottom = (stacks - 2) * slices;        GLushort top = bottom + slices;        for (int i = 0; i < slices; i++) {                *(index++) = bottom + i;            *(index++) = bottom + (i + 1) % slices;            *(index++) = top;        }                glGenBuffers(1, &vbo.second);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);        const int BYTES_PER_INDEX = sizeof(GLushort);        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);        delete[] indexData;        } else {        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);    }    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     glVertexPointer(3, GL_FLOAT, 0, 0);    glNormalPointer(GL_FLOAT, 0, 0);            glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);            glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);} 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;const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat);const int NUM_BYTES_PER_INDEX = sizeof(GLushort); void GeometryCache::renderSphere(float radius, int slices, int stacks, const glm::vec4& color, bool solid) {    VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)];    int vertices = slices * (stacks - 1) + 2;        int indices = slices * stacks * NUM_VERTICES_PER_TRIANGULATED_QUAD;    if (vbo.first == 0) {                GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];        GLfloat* vertex = vertexData;         // south pole        *(vertex++) = 0.0f;        *(vertex++) = 0.0f;        *(vertex++) = -1.0f;         //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 = cosf(phi);                        for (int j = 0; j < slices; j++) {                float theta = TWO_PI * (float)j / (float)slices;                 *(vertex++) = sinf(theta) * radius;                *(vertex++) = cosf(theta) * radius;                *(vertex++) = z;            }        }         // north pole        *(vertex++) = 0.0f;        *(vertex++) = 0.0f;        *(vertex++) = 1.0f;                glGenBuffers(1, &vbo.first);        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);        delete[] vertexData;                GLushort* indexData = new GLushort[indices];        GLushort* index = indexData;         // 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;        }         // (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;                                *(index++) = bottom + next;                *(index++) = bottom + j;                *(index++) = top + next;            }        }                // 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;        }                glGenBuffers(1, &vbo.second);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);        delete[] indexData;        } else {        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);    }    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     glVertexPointer(3, GL_FLOAT, 0, 0);    glNormalPointer(GL_FLOAT, 0, 0);     glPushMatrix();    glScalef(radius, radius, radius);    if (solid) {        glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);    } else {        glDrawRangeElementsEXT(GL_LINES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);    }    glPopMatrix();     glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);} void GeometryCache::renderSquare(int xDivisions, int yDivisions) {    VerticesIndices& vbo = _squareVBOs[IntPair(xDivisions, yDivisions)];    int xVertices = xDivisions + 1;    int yVertices = yDivisions + 1;    int vertices = xVertices * yVertices;    int indices = 2 * 3 * xDivisions * yDivisions;    if (vbo.first == 0) {        GLfloat* vertexData = new GLfloat[vertices * 3];        GLfloat* vertex = vertexData;        for (int i = 0; i <= yDivisions; i++) {            float y = (float)i / yDivisions;                        for (int j = 0; j <= xDivisions; j++) {                *(vertex++) = (float)j / xDivisions;                *(vertex++) = y;                *(vertex++) = 0.0f;            }        }                glGenBuffers(1, &vbo.first);        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);        delete[] vertexData;                GLushort* indexData = new GLushort[indices];        GLushort* index = indexData;        for (int i = 0; i < yDivisions; i++) {            GLushort bottom = i * xVertices;            GLushort top = bottom + xVertices;            for (int j = 0; j < xDivisions; j++) {                int next = j + 1;                                *(index++) = bottom + j;                *(index++) = top + next;                *(index++) = top + j;                                *(index++) = bottom + j;                *(index++) = bottom + next;                *(index++) = top + next;            }        }                glGenBuffers(1, &vbo.second);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);        delete[] indexData;            } else {        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);    }    glEnableClientState(GL_VERTEX_ARRAY);     // all vertices have the same normal    glNormal3f(0.0f, 0.0f, 1.0f);        glVertexPointer(3, GL_FLOAT, 0, 0);            glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);            glDisableClientState(GL_VERTEX_ARRAY);        glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);} void GeometryCache::renderHalfCylinder(int slices, int stacks) {    VerticesIndices& vbo = _halfCylinderVBOs[IntPair(slices, stacks)];    int vertices = (slices + 1) * stacks;    int indices = 2 * 3 * slices * (stacks - 1);    if (vbo.first == 0) {            GLfloat* vertexData = new GLfloat[vertices * 2 * 3];        GLfloat* vertex = vertexData;        for (int i = 0; i <= (stacks - 1); i++) {            float y = (float)i / (stacks - 1);                        for (int j = 0; j <= slices; j++) {                float theta = 3.0f * PI_OVER_TWO + PI * (float)j / (float)slices;                 //normals                *(vertex++) = sinf(theta);                *(vertex++) = 0;                *(vertex++) = cosf(theta);                 // vertices                *(vertex++) = sinf(theta);                *(vertex++) = y;                *(vertex++) = cosf(theta);            }        }                glGenBuffers(1, &vbo.first);        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);        delete[] vertexData;                GLushort* indexData = new GLushort[indices];        GLushort* index = indexData;        for (int i = 0; i < stacks - 1; i++) {            GLushort bottom = i * (slices + 1);            GLushort top = bottom + slices + 1;            for (int j = 0; j < slices; j++) {                int next = j + 1;                                *(index++) = bottom + j;                *(index++) = top + next;                *(index++) = top + j;                                *(index++) = bottom + j;                *(index++) = bottom + next;                *(index++) = top + next;            }        }                glGenBuffers(1, &vbo.second);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);        delete[] indexData;        } else {        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);    }    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     glNormalPointer(GL_FLOAT, 6 * sizeof(float), 0);    glVertexPointer(3, GL_FLOAT, (6 * sizeof(float)), (const void *)(3 * sizeof(float)));            glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);            glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);} void GeometryCache::renderCone(float base, float height, int slices, int stacks) {    VerticesIndices& vbo = _halfCylinderVBOs[IntPair(slices, stacks)];    int vertices = (stacks + 2) * slices;    int baseTriangles = slices - 2;    int indices = NUM_VERTICES_PER_TRIANGULATED_QUAD * slices * stacks + NUM_VERTICES_PER_TRIANGLE * baseTriangles;    if (vbo.first == 0) {        GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX * 2];        GLfloat* vertex = vertexData;        // cap        for (int i = 0; i < slices; i++) {            float theta = TWO_PI * i / slices;                        //normals            *(vertex++) = 0.0f;            *(vertex++) = 0.0f;            *(vertex++) = -1.0f;             // vertices            *(vertex++) = cosf(theta);            *(vertex++) = sinf(theta);            *(vertex++) = 0.0f;        }        // body        for (int i = 0; i <= stacks; i++) {            float z = (float)i / stacks;            float radius = 1.0f - z;                        for (int j = 0; j < slices; j++) {                float theta = TWO_PI * j / slices;                 //normals                *(vertex++) = cosf(theta) / SQUARE_ROOT_OF_2;                *(vertex++) = sinf(theta) / SQUARE_ROOT_OF_2;                *(vertex++) = 1.0f / SQUARE_ROOT_OF_2;                 // vertices                *(vertex++) = radius * cosf(theta);                *(vertex++) = radius * sinf(theta);                *(vertex++) = z;            }        }                glGenBuffers(1, &vbo.first);        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);        delete[] vertexData;                GLushort* indexData = new GLushort[indices];        GLushort* index = indexData;        for (int i = 0; i < baseTriangles; i++) {            *(index++) = 0;            *(index++) = i + 2;            *(index++) = i + 1;        }        for (int i = 1; i <= stacks; i++) {            GLushort bottom = i * slices;            GLushort top = bottom + slices;            for (int j = 0; j < slices; j++) {                int next = (j + 1) % slices;                                *(index++) = bottom + j;                *(index++) = top + next;                *(index++) = top + j;                                *(index++) = bottom + j;                *(index++) = bottom + next;                *(index++) = top + next;            }        }                glGenBuffers(1, &vbo.second);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);        glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);        delete[] indexData;            } else {        glBindBuffer(GL_ARRAY_BUFFER, vbo.first);        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);    }    glEnableClientState(GL_VERTEX_ARRAY);    glEnableClientState(GL_NORMAL_ARRAY);     int stride = NUM_VERTICES_PER_TRIANGULATED_QUAD * sizeof(float);    glNormalPointer(GL_FLOAT, stride, 0);    glVertexPointer(NUM_COORDS_PER_VERTEX, GL_FLOAT, stride, (const void *)(NUM_COORDS_PER_VERTEX * sizeof(float)));        glPushMatrix();    glScalef(base, base, height);        glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);        glPopMatrix();        glDisableClientState(GL_VERTEX_ARRAY);    glDisableClientState(GL_NORMAL_ARRAY);        glBindBuffer(GL_ARRAY_BUFFER, 0);    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);} void GeometryCache::renderGrid(int xDivisions, int yDivisions, const glm::vec4& color) {    QOpenGLBuffer& buffer = _gridBuffers[IntPair(xDivisions, yDivisions)];    int vertices = (xDivisions + 1 + yDivisions + 1) * 2;    if (!buffer.isCreated()) {        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;

Lines 1–500 of 2214.