//// 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. 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 <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;