History

Merge pull request #1354 from HifiExperiments/torus

add torus rendering

ksuprynowicz committed 1 year ago

Commit 3a5fd2e2 parents 95c24e7 412988a12 files · +207 −36Browse files

Showing the changes to libraries/render-utils/src/GeometryCache.cpp (1 of 12 files). Show all

Unified · Split

libraries/render-utils/src/GeometryCache.cpp+135−20
@@ -19,6 +19,7 @@ · 18 unmodified lines
1919 #include <QtCore/QFileInfo>
2020 #include <QtNetwork/QNetworkReply>
2121
22+#include <glm/gtx/transform.hpp>
2223 #include <shared/Shapes.h>
2324 #include <shared/PlatformHacks.h>
2425
@@ -590,8 +591,7 @@ void GeometryCache::buildShapes() { · 565 unmodified lines
590591 extrudePolygon<64>(_shapes[Cone], _shapeVertices, _shapeIndices, true);
591592 // Circle renders as flat Cylinder
592593 extrudePolygon<64>(_shapes[Circle], _shapeVertices, _shapeIndices);
593− // Not implemented yet:
594− //Torus,
594+ //Torus is implemented in renderTorus, not with ShapeData, because the inner radius can change
595595 }
596596
597597 const GeometryCache::ShapeData * GeometryCache::getShapeData(const Shape shape) const {
@@ -696,6 +696,9 @@ void GeometryCache::releaseID(int id) { · 98 unmodified lines
696696
697697 _lastRegisteredGridBuffer.remove(id);
698698 _registeredGridBuffers.remove(id);
699+
700+ _lastRegisteredTorusBuffer.remove(id);
701+ _registeredTorusBuffers.remove(id);
699702 }
700703
701704 void GeometryCache::initializeShapePipelines() {
@@ -1618,18 +1621,132 @@ void GeometryCache::renderDashedLine(gpu::Batch& batch, const glm::vec3& start, · 916 unmodified lines
16181621 batch.draw(gpu::LINES, details.vertices, 0);
16191622 }
16201623
1624+void GeometryCache::renderTorus(gpu::Batch& batch, float innerRadius, gpu::BufferPointer& colorBuffer, int id) {
1625+ bool registered = (id != UNKNOWN_ID);
1626+ BatchItemDetails& details = _registeredTorusBuffers[id];
1627+
1628+ // if this is a registered, and we have buffers, then check to see if the geometry changed and rebuild if needed
1629+ if (registered && details.isCreated) {
1630+ if (_lastRegisteredTorusBuffer[id] != innerRadius) {
1631+ details.clear();
1632+ _lastRegisteredTorusBuffer[id] = innerRadius;
1633+#ifdef WANT_DEBUG
1634+ qCDebug(renderutils) << "renderTorus()... RELEASING REGISTERED";
1635+#endif // def WANT_DEBUG
1636+ }
1637+ }
1638+
1639+ if (!details.isCreated) {
1640+ const int NUM_DIVISIONS = 64;
1641+ const float ANGLE_STEP = 2.0f * ((float)M_PI) / NUM_DIVISIONS;
1642+ const int FLOATS_PER_VERTEX = 3 + 3 + 2 + 3; // vertices + normals + tex coords + tangents
1643+ details.isCreated = true;
1644+ details.vertices = 6 * (NUM_DIVISIONS + 1) * (NUM_DIVISIONS + 1);
1645+ details.vertexSize = FLOATS_PER_VERTEX;
1646+
1647+ auto verticesBuffer = std::make_shared<gpu::Buffer>();
1648+ auto indicesBuffer = std::make_shared<gpu::Buffer>();
1649+ auto streamFormat = std::make_shared<gpu::Stream::Format>();
1650+ auto stream = std::make_shared<gpu::BufferStream>();
1651+
1652+ details.verticesBuffer = verticesBuffer;
1653+ details.uniformBuffer = indicesBuffer; // we use the uniformBuffer to store the incides
1654+ details.streamFormat = streamFormat;
1655+ details.stream = stream;
1656+
1657+ details.streamFormat->setAttribute(gpu::Stream::POSITION, 0, POSITION_ELEMENT);
1658+ details.streamFormat->setAttribute(gpu::Stream::NORMAL, 0, NORMAL_ELEMENT, 3 * sizeof(float));
1659+ details.streamFormat->setAttribute(gpu::Stream::TEXCOORD0, 0, TEXCOORD0_ELEMENT, 6 * sizeof(float));
1660+ details.streamFormat->setAttribute(gpu::Stream::TANGENT, 0, TANGENT_ELEMENT, 8 * sizeof(float));
1661+ details.streamFormat->setAttribute(gpu::Stream::COLOR, gpu::Stream::COLOR, COLOR_ELEMENT, 0, gpu::Stream::PER_INSTANCE);
1662+
1663+ details.stream->addBuffer(details.verticesBuffer, 0, details.streamFormat->getChannels().at(0)._stride);
1664+
1665+ // Build our initial circle. Keep track of the center point for normal calculations.
1666+ glm::vec3 center = glm::vec3(0.5f - innerRadius, 0.0f, 0.0f);
1667+ std::array<glm::vec3, NUM_DIVISIONS + 1> points;
1668+ for (int i = 0; i <= NUM_DIVISIONS; i++) {
1669+ // Inner radius only affects X. Y still needs to be -0.5 -> 0.5.
1670+ points[i] = center + glm::vec3(innerRadius * glm::cos(i * ANGLE_STEP), 0.5f * glm::sin(i * ANGLE_STEP), 0.0f);
1671+ }
1672+ glm::mat3 normalMatrix = glm::transpose(glm::inverse(glm::scale(glm::vec3(1.0f, 0.5f / innerRadius, 1.0f))));
1673+
1674+ // Build all of our vertex data
1675+ float* vertexData = new float[details.vertices * FLOATS_PER_VERTEX];
1676+ float* vertex = vertexData;
1677+ for (int y = 0; y <= NUM_DIVISIONS; y++) {
1678+ const float ANGLE = y * ANGLE_STEP;
1679+ for (int i = 0; i <= NUM_DIVISIONS; i++) {
1680+ glm::vec3 currentCenter = fabs(center.x) * glm::vec3(glm::cos(ANGLE), 0.0f, glm::sin(ANGLE));
1681+ // Position
1682+ glm::vec3 currentPoint = glm::vec3(0.0f, points[i].y, 0.0f) + fabs(points[i].x) * glm::vec3(glm::cos(ANGLE), 0.0f, glm::sin(ANGLE));
1683+ *(vertex++) = currentPoint.x;
1684+ *(vertex++) = currentPoint.y;
1685+ *(vertex++) = currentPoint.z;
1686+ // Normal
1687+ glm::vec3 currentNormal = glm::normalize(normalMatrix * glm::normalize(currentPoint - currentCenter));
1688+ *(vertex++) = currentNormal.x;
1689+ *(vertex++) = currentNormal.y;
1690+ *(vertex++) = currentNormal.z;
1691+ // UV
1692+ glm::vec2 currentUV = glm::vec2((float)i / NUM_DIVISIONS, (float)y / NUM_DIVISIONS);
1693+ *(vertex++) = currentUV.x;
1694+ *(vertex++) = currentUV.y;
1695+ // Tangent
1696+ int nextIndex = (i + 1) % (NUM_DIVISIONS + 1) + (i / (NUM_DIVISIONS + 1));
1697+ glm::vec3 currentTangent = glm::normalize(glm::cross(currentNormal, points[nextIndex] - points[i]));
1698+ *(vertex++) = currentTangent.x;
1699+ *(vertex++) = currentTangent.y;
1700+ *(vertex++) = currentTangent.z;
1701+ }
1702+ }
1703+
1704+ details.verticesBuffer->append(sizeof(float) * FLOATS_PER_VERTEX * details.vertices, (gpu::Byte*)vertexData);
1705+ delete[] vertexData;
1706+
1707+ // Build our indices
1708+ for (int y = 0; y < NUM_DIVISIONS; y++) {
1709+ for (int i = 0; i < NUM_DIVISIONS; i++) {
1710+ const int baseIndex = i + (NUM_DIVISIONS + 1) * y;
1711+ details.uniformBuffer->append((uint16_t)baseIndex);
1712+ details.uniformBuffer->append((uint16_t)(baseIndex + 1));
1713+ details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 1));
1714+ details.uniformBuffer->append((uint16_t)(baseIndex + 1));
1715+ details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 2));
1716+ details.uniformBuffer->append((uint16_t)(baseIndex + NUM_DIVISIONS + 1));
1717+ }
1718+ }
1719+
1720+#ifdef WANT_DEBUG
1721+ if (registered) {
1722+ qCDebug(renderutils) << "new registered torus buffer made -- _registeredTorusBuffers:"
1723+ << _registeredTorusBuffers.size();
1724+ } else {
1725+ qCDebug(renderutils) << "new torus buffer made -- _registeredTorusBuffers:" << _registeredTorusBuffers.size();
1726+ }
1727+#endif
1728+ }
1729+
1730+ // TODO: instanced rendering
1731+ gpu::BufferView colorView(colorBuffer, COLOR_ELEMENT);
1732+ batch.setInputBuffer(gpu::Stream::COLOR, colorView);
1733+ batch.setInputStream(0, *details.stream);
1734+ batch.setInputFormat(details.streamFormat);
1735+ batch.setIndexBuffer(gpu::Type::UINT16, details.uniformBuffer, 0); // indices are stored in uniformBuffer
1736+ batch.drawIndexed(gpu::TRIANGLES, details.vertices, 0);
1737+}
16211738
16221739 int GeometryCache::BatchItemDetails::population = 0;
16231740
16241741 GeometryCache::BatchItemDetails::BatchItemDetails() :
1625−verticesBuffer(NULL),
1626−normalBuffer(NULL),
1627−colorBuffer(NULL),
1628−streamFormat(NULL),
1629−stream(NULL),
1630−vertices(0),
1631−vertexSize(0),
1632−isCreated(false) {
1742+ verticesBuffer(NULL),
1743+ normalBuffer(NULL),
1744+ colorBuffer(NULL),
1745+ streamFormat(NULL),
1746+ stream(NULL),
1747+ vertices(0),
1748+ vertexSize(0),
1749+ isCreated(false) {
16331750 population++;
16341751 #ifdef WANT_DEBUG
16351752 qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************";
@@ -1637,14 +1754,14 @@ isCreated(false) { · 1 unmodified line
16371754 }
16381755
16391756 GeometryCache::BatchItemDetails::BatchItemDetails(const GeometryCache::BatchItemDetails& other) :
1640−verticesBuffer(other.verticesBuffer),
1641−normalBuffer(other.normalBuffer),
1642−colorBuffer(other.colorBuffer),
1643−streamFormat(other.streamFormat),
1644−stream(other.stream),
1645−vertices(other.vertices),
1646−vertexSize(other.vertexSize),
1647−isCreated(other.isCreated) {
1757+ verticesBuffer(other.verticesBuffer),
1758+ normalBuffer(other.normalBuffer),
1759+ colorBuffer(other.colorBuffer),
1760+ streamFormat(other.streamFormat),
1761+ stream(other.stream),
1762+ vertices(other.vertices),
1763+ vertexSize(other.vertexSize),
1764+ isCreated(other.isCreated) {
16481765 population++;
16491766 #ifdef WANT_DEBUG
16501767 qCDebug(renderutils) << "BatchItemDetails()... population:" << population << "**********************************";
@@ -1728,8 +1845,6 @@ void GeometryCache::useGridPipeline(gpu::Batch& batch, GridBuffer gridBuffer, bo · 77 unmodified lines
17281845 batch.setUniformBuffer(0, gridBuffer);
17291846 }
17301847
1731−
1732−
17331848 class SimpleProgramKey {
17341849 public:
17351850 enum FlagBit {